桥的题目列表

桥:

定义:删除一条边,使得原图的连通分量增加的,即为桥。

 

一般容易出现的trick

①重边

②多个图

 

题目列表

①UVA 796 模板题(一)

②HDU4738 重边+许多坑点(二)

 

一:UVA796 

题目大意:给你一个图,问有几个桥?先输入u,在输入(cnt)个和他连接的边

思路:模板题,不多说了。

 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 }
View Code

 

二:HDU4738

题目大意:周瑜炸桥,给你一个图,每个顶点之间都有一条边,边上都有val个人把手,如何炸桥能使得这个图不连通。炸桥所需要的人数必须是>=val的人数的,问最少需要几个人?

思路:找出所有的桥,然后枚举一下val即可。

这里有好多个trick

①图可能本来就不连通的

②如果该桥的val是0的话,也至少要派一个人过去。

③可能有重边(重边的val定义成inf即可)

由于。。。我把ans.clear()放在最后面了,结果卡了我1h的WA,

教训:人的数目,初始化的位置

 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 }
View Code

 

三:

 

四:

 

五:

 

六:

 

posted @ 2016-08-25 10:19  知る奇迹に  阅读(224)  评论(0编辑  收藏  举报