【HDU 4738 Caocao's Bridges】BCC 找桥

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738

题意:给定一个n个节点m条边的无向图(可能不连通、有重边),每条边有一个权值。判断其连通性,若双连通,输出-1;若非连通,输出0;否则,输出权值最小的桥的权值。

思路:进行双连通域分解,记下连通块的个数和所有桥的情况,对应输出结果即可。

注意对重边的处理。这里我按照上一道题学到的姿势如法炮制:先把所有边按“字典序”排序(u, v, w),这样重边聚集在一起了,然后扫描一遍,发现重边即在结构体Edge中打重边标记;由于重边一定不是桥,因此选哪个的权值实际上无所谓。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 #define CLEAR(A, X) memset(A, X, sizeof(A))
  6 #define REP(N) for(int i=0; i<(N); i++)
  7 #define REPE(N) for(int i=1; i<=(N); i++)
  8 #define FREAD(FN) freopen((FN), "r", stdin)
  9 #define pb(a) push_back(a)
 10
 11 using namespace std;
 12
 13 const int MAX_N = 1005;
 14 const int MAX_M = 2000005;
 15 const int INF = 10005;
 16 int n, m;
 17
 18 struct Edge
 19 {
 20     int v, next;
 21     int w;
 22     bool isBrg;
 23     bool isDup;
 24 }edges[MAX_M];
 25 int numE;
 26 int head[MAX_N];
 27 int low[MAX_N], dfn[MAX_N], clock;
 28 int inStack[MAX_N], S[MAX_N], topS;
 29 int block, belong[MAX_N];
 30 int numBrg;
 31 int cnt;//连通块个数
 32
 33 void init(){
 34     numE = 0;
 35     clock = block = topS = 0;
 36     numBrg = 0;
 37     CLEAR(low, 0);
 38     CLEAR(dfn, 0);
 39     CLEAR(head, -1);
 40     CLEAR(belong, 0);
 41     CLEAR(inStack, 0);
 42 }
 43
 44
 45 void addEdge(int u, int v, int w, bool isDup){
 46     edges[numE].v = v;
 47     edges[numE].w = w;
 48     edges[numE].isBrg = 0;
 49     edges[numE].isDup = isDup;
 50     edges[numE].next = head[u];
 51     head[u] = numE++;
 52
 53     //反向边
 54     edges[numE].v = u;
 55     edges[numE].w = w;
 56     edges[numE].isBrg = 0; //这里之前忘清零了,一直WA。。。
 57     edges[numE].isDup = isDup;
 58     edges[numE].next = head[v];
 59     head[v] = numE++;
 60 }
 61
 62 void bcc(int u, int p, int isDup){
 63     low[u] = dfn[u] = ++clock;
 64     S[topS++] = u;
 65     inStack[u] = 1;
 66     for(int i=head[u]; i != -1; i = edges[i].next){
 67         int v = edges[i].v;
 68         if(v == p && (!isDup)) continue;
 69         if(!dfn[v]){
 70             bcc(v, u, edges[i].isDup);
 71             low[u] = min(low[u], low[v]);
 72             if(low[v] > dfn[u]){//bridge
 73                 numBrg++;
 74                 edges[i].isBrg = 1;
 75                 edges[i^1].isBrg = 1;
 76             }
 77         }else if(inStack[v]){//backward
 78             low[u] = min(low[u], dfn[v]);
 79         }
 80     }
 81     if(low[u] == dfn[u]){//new bcc
 82         block++;
 83         int t;
 84         do{
 85             t = S[--topS];
 86             inStack[t] = 0;
 87             belong[t] = block;
 88         }while(t != u);
 89     }
 90 }
 91
 92 struct Node
 93 {
 94     int u, v, w;
 95     Node(){}
 96     Node(int uu, int vv, int ww):u(uu), v(vv), w(ww){}
 97 }nodes[MAX_M];
 98 bool cmp(Node a, Node b){
 99     if(a.u == b.u){
100         if(a.v == b.v) return a.w < b.w;
101         return a.v < b.v;
102     }
103     return a.u < b.u;
104 }
105 bool same(Node a, Node b){
106     return a.u == b.u && a.v == b.v;
107 }
108
109 int main()
110 {
111     FREAD("4738.txt");
112     while(~scanf("%d%d", &n, &m) && !(n==0 && m==0)){
113         init();
114         REP(m){
115             int u, v, w;
116             scanf("%d%d%d", &u, &v, &w);
117             if(u > v) swap(u, v);//保持顺序
118             nodes[i] = Node(u, v, w);
119         }
120         sort(nodes, nodes+m, cmp);
121         int cur = 0, i = 1;
122         int flagDup = 0;
123         while(cur < m){
124             while(i < m && same(nodes[cur], nodes[i])){
125                 flagDup = 1;
126                 i++;
127             }//重边一定不是桥,
128             if(flagDup) addEdge(nodes[cur].u, nodes[cur].v, nodes[cur].w, true);
129             else addEdge(nodes[cur].u, nodes[cur].v, nodes[cur].w, false);
130             flagDup = 0;
131             cur = i++;
132         }
133         cnt = 0;
134         REPE(n){
135             if(!dfn[i]){
136                 bcc(i, 0, 0);
137                 cnt++;
138             }
139         }
140         int ans = INF;
141         if(cnt > 1) ans = 0;//非连通
142         else if(cnt==1 && !numBrg) ans = -1;//边双连通
143         else{//有桥
144             // REPE(n){
145             //     for(int j=head[i]; j != -1; j = edges[j].next){
146             //         int v = edges[j].v;
147             //         if(belong[i] != belong[v])
148             //             ans = min(ans, edges[j].w);
149             //     }
150             // }
151             REPE(numE){
152                 if(edges[i].isBrg)
153                     ans = min(ans, edges[i].w);
154             }
155             if(ans == 0) ans = 1;//至少派一人
156         }
157         printf("%d\n", ans);
158     }
159     return 0;
160 }

判桥用 edges[i].isBrg 或 belong[u] == belong[v]都可以,二者等价。

多组样例,我开始用第一种但忘记在addEdge中把isBrg清零了才会WA。

时间: 2025-01-13 04:53:35

【HDU 4738 Caocao&#39;s Bridges】BCC 找桥的相关文章

hdu 5280 Senior&amp;#39;s Array

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5280 问题描述 某天学姐姐得到了一个数组A ,在这个数组的所有非空区间中,她找出了一个区间和最大的,并把这个区间和定义为这个数组的美丽值. 但是她觉得这个数组不够美,于是决定修理一下这个数组. 学姐姐将会进行一次操作,把原数组中的某个数修改为P (必须修改). 最后她想使得修改后的数组尽可能美丽.请你帮助她计算经过修理后,这个数组的美丽值最大能是多少? #include <iostream> #i

hdu 3509 Buge&amp;#39;s Fibonacci Number Problem

点击此处即可传送 hdu 3509 题目大意:F1 = f1, F2 = f2;; F(n) = a*F(n-1) + b*F(n-2); S(n) = F1^k + F2^k +-.+Fn^k; 求S(n) mod m; 解题思路: 1:首先一个难题就是怎么判断矩阵的维数(矩阵的维数是个变量) 解决方法:开一个比较大的数组,然后再用一个公有变量记一下就行了,具体详见代码: 2:k次方,找规律: 具体上代码吧: /* 2015 - 8 - 16 晚上 Author: ITAK 今日的我要超越昨日

hdu 5281 Senior&amp;#39;s Gun

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5281 题目大意:学姐姐是一个酷酷的枪手. 她常常会随身携带n 把枪,每把枪有一个攻击力a[i] . 有一天她遇到了m 只怪兽,每只怪兽有一个防御力b[j] .现在她决定用手中的枪消灭这些怪兽. 学姐姐可以用第i 把枪消灭第j 只怪兽当且仅当b[j]≤a[i] ,同时她会获得a[i]−b[j] 的分数. 每把枪至多只能使用一次,怪兽死后也不会复活.现在学姐姐想知道她最多能得到多少分(她可以不用消灭所有

xml dom4j-xpath路径问题,/users/user[username=&amp;amp;#39;张三&amp;amp;#39;]路径问什么找不到相应的文本?

问题描述 xpath路径问题,/users/user[username='张三']路径问什么找不到相应的文本? 我是想经过一个名字(张三)找到他其他文本元素(nickname,password),但是这个路径(/users/user[username='张三'])问什么不对看视频上是这样的啊? public User load(String username){//根据用户名获取用户对象,把xml文件里面的节点元素文本(对象的属性保存在xml)set给对像 String path = "/use

hdu 5334 MZL&amp;#39;s xor

hdu 5334 的传送门 MZL loves xor very much.Now he gets an array A.The length of A is n.He wants to know the xor of all (Ai+Aj)(1≤i,j≤n) The xor of an array B is defined as B1 xor B2-xor Bn Input Multiple test cases, the first line contains an integer T(no

hdu 5349 MZL&amp;#39;s simple problem

hdu 5349 的传送门 Problem Description A simple problem Problem Description You have a multiple set,and now there are three kinds of operations: 1 x : add number x to set 2 : delete the minimum number (if the set is empty now,then ignore it) 3 : query the

hdu 1250 Hat&amp;#39;s Fibonacci

点击此处即可传送hdu 1250 Problem Description A Fibonacci sequence is calculated by adding the previous two members the sequence, with the first two members being both 1. F(1) = 1, F(2) = 1, F(3) = 1,F(4) = 1, F(n>4) = F(n - 1) + F(n-2) + F(n-3) + F(n-4) Your

hdu 2147 kiki&amp;#39;s game

http://acm.hdu.edu.cn/showproblem.php?pid=2147 这是一个巴什博弈的题,当两个数至少有一个数是偶数先手必胜 代码如下: #include <iostream> #include <cstdio> using namespace std; int main() { int m,n; while(cin>>m>>n,m,n) { if(m%2 && n%2) puts("What a pity

hdu 1756 Cupid&amp;#39;s Arrow 计算几何

    判断点是否在多边形内部     对于任意四边形,可以随机选取一条射线向外延伸,如果相交边数为奇数,则在内,偶数,则在外    这题无需考虑在边上的情况 /* author:jxy lang:C/C++ university:China,Xidian University **If you need to reprint,please indicate the source** 给定n个点的坐标,这n个点依次围成一闭合多边形,再给一点(x,y),判断它是否在多边形中. */ #includ