桥的题目列表
桥:
定义:删除一条边,使得原图的连通分量增加的,即为桥。
一般容易出现的trick
①重边
②多个图
题目列表
①UVA 796 模板题(一)
②HDU4738 重边+许多坑点(二)
一:UVA796
题目大意:给你一个图,问有几个桥?先输入u,在输入(cnt)个和他连接的边
思路:模板题,不多说了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //看看会不会爆int!数组会不会少了一维! 2 //取物问题一定要小心先手胜利的条件 3 #include <bits/stdc++.h> 4 using namespace std; 5 #define LL long long 6 #define ALL(a) a.begin(), a.end() 7 #define pb push_back 8 #define mk make_pair 9 #define fi first 10 #define se second 11 const int maxn = 1000 + 5; 12 vector<int> G[maxn]; 13 vector<pair<int, int> > ans; 14 int pre[maxn], low[maxn]; 15 int n, dfstime; 16 17 int dfs(int u, int fa){ 18 int lowu = pre[u] = ++dfstime; 19 int child = 0; 20 int len = G[u].size(); 21 for (int i = 0; i < len; i++){ 22 int v = G[u][i]; 23 if (!pre[v]){ 24 child++; 25 int lowv = dfs(v, u); 26 lowu = min(lowv, lowu); 27 if (lowv > pre[u]){ 28 ans.pb(mk(u, v)); 29 } 30 } 31 else if (pre[v] < pre[u] && v != fa){ 32 lowu = min(lowu, pre[v]); 33 } 34 } 35 return lowu; 36 } 37 38 int main(){ 39 while (scanf("%d", &n) == 1){ 40 for (int i = 1; i <= n; i++){ 41 G[i].clear(); 42 pre[i] = 0; 43 } 44 for (int i = 1; i <= n; i++){ 45 int u, v, cnt; 46 scanf("%d (%d)", &u, &cnt); u++; 47 for (int j = 1; j <= cnt; j++){ 48 scanf("%d", &v); v++; 49 G[u].pb(v); G[v].pb(u); 50 } 51 } 52 dfstime = 0; 53 for (int i = 1; i <= n; i++){ 54 if (!pre[i]){ 55 dfs(i, -1); 56 } 57 } 58 int len = ans.size(); 59 for (int i = 0; i < len; i++) 60 if (ans[i].fi > ans[i].se) swap(ans[i].fi, ans[i].se); 61 sort(ALL(ans)); 62 printf("%d critical links\n", len); 63 for (int i = 0; i < len; i++){ 64 printf("%d - %d\n", ans[i].first - 1, ans[i].second - 1); 65 } 66 printf("\n"); 67 ans.clear(); 68 } 69 return 0; 70 }
二:HDU4738
题目大意:周瑜炸桥,给你一个图,每个顶点之间都有一条边,边上都有val个人把手,如何炸桥能使得这个图不连通。炸桥所需要的人数必须是>=val的人数的,问最少需要几个人?
思路:找出所有的桥,然后枚举一下val即可。
这里有好多个trick
①图可能本来就不连通的
②如果该桥的val是0的话,也至少要派一个人过去。
③可能有重边(重边的val定义成inf即可)
由于。。。我把ans.clear()放在最后面了,结果卡了我1h的WA,
教训:人的数目,初始化的位置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //看看会不会爆int!数组会不会少了一维! 2 //取物问题一定要小心先手胜利的条件 3 #include <bits/stdc++.h> 4 using namespace std; 5 #define LL long long 6 #define ALL(a) a.begin(), a.end() 7 #define pb push_back 8 #define mk make_pair 9 #define fi first 10 #define se second 11 const int maxn = 1000 + 5; 12 const int inf = 0x3f3f3f3f; 13 vector<int> G[maxn]; 14 vector<pair<int, int> > ans; 15 int a[maxn][maxn]; 16 int pre[maxn], low[maxn]; 17 int n, p, dfstime; 18 19 int dfs(int u, int fa){ 20 int lowu = pre[u] = ++dfstime; 21 int child = 0; 22 int len = G[u].size(); 23 for (int i = 0; i < len; i++){ 24 int v = G[u][i]; 25 if (!pre[v]){ 26 child++; 27 int lowv = dfs(v, u); 28 lowu = min(lowv, lowu); 29 if (lowv > pre[u] && a[u][v] != inf){ 30 ans.pb(mk(u, v)); 31 } 32 } 33 else if (pre[v] < pre[u] && v != fa){ 34 lowu = min(lowu, pre[v]); 35 } 36 } 37 return lowu; 38 } 39 40 int main(){ 41 while (scanf("%d%d", &n, &p) == 2 && n + p){ 42 for (int i = 1; i <= n; i++){ 43 G[i].clear(); 44 pre[i] = 0; 45 } 46 ans.clear(); 47 memset(a, -1, sizeof(a)); 48 for (int i = 1; i <= p; i++){ 49 int u, v, cnt; 50 scanf("%d %d %d", &u, &v, &cnt); 51 G[u].pb(v); G[v].pb(u); 52 if (a[u][v] != -1){ 53 a[v][u] = a[u][v] = inf; 54 continue; 55 } 56 a[u][v] = a[v][u] = cnt; 57 } 58 dfstime = 0; 59 int cnt = 0; 60 for (int i = 1; i <= n; i++){ 61 if (!pre[i]){ 62 cnt++; 63 dfs(i, -1); 64 } 65 } 66 if (cnt > 1){ 67 printf("0\n"); continue; 68 } 69 int len = ans.size(); 70 int res = 0x3f3f3f3f; 71 for (int i = 0; i < len; i++){ 72 res = min(res, a[ans[i].fi][ans[i].se]); 73 } 74 ///①0个人的桥也需要一个人去炸②一开始可能就不连通 75 if (res == 0 && len != 0) res += 1; 76 if (len == 0) res = -1; 77 printf("%d\n", res); 78 } 79 return 0; 80 }
三:
四:
五:
六: