双连通

poj 3352 Road Construction && poj 3177 Redundant Paths

给一个无向图,问最少需要添加多少条边,使它成为双连通图。

做法:边双连通缩点,成为一棵树。若要使得任意一棵树,变成一个双连通图,那么至少增加的边数 =(度数为1的结点数 + 1 )/ 2

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cstdio>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<set>
  9 #include<map>
 10 #include<queue>
 11 #include<bitset>
 12
 13 using namespace std;
 14
 15
 16 #pragma comment(linker, "/STACK:1024000000,1024000000")
 17 #define inf 0x3f3f3f3f
 18 #define eps 1e-9
 19 #define FOR(i,s,t) for(int i = s; i < t; ++i )
 20 #define REP(i,s,t) for( int i = s; i <= t; ++i )
 21 #define pii pair<int,int>
 22 #define MP make_pair
 23 #define ls i << 1
 24 #define rs ls | 1
 25 #define md ((ll + rr) >> 1)
 26 #define lson ll, md, ls
 27 #define rson md + 1, rr, rs
 28 #define LL  long long
 29 #define N 1010
 30 #define M 2020
 31 #define Pi acos(-1.0)
 32 #define mod 1000007
 33 #define ULL unsigned long long
 34
 35 int fst[N], nxt[M], vv[M], e;
 36 void init(){
 37     memset(fst, -1, sizeof fst); e = 0;
 38 }
 39 void add(int u, int v){
 40     vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
 41 }
 42
 43 int bccno[N], pre[N], dc, bcnt;
 44 bool cut[M];
 45 int dfs(int u, int p){
 46     int lowu = pre[u] = ++dc;
 47     for(int i = fst[u]; ~i; i = nxt[i]){
 48         int v = vv[i];
 49         if(!pre[v]){
 50             int lowv = dfs(v, u);
 51             lowu = min(lowu, lowv);
 52             if(lowv > pre[u]){
 53                 cut[i] = cut[i^1] = 1;
 54             }
 55         }
 56         else if(v != p)
 57             lowu = min(lowu, pre[v]);
 58     }
 59     return lowu;
 60 }
 61 void dfs2(int u, int cnt){
 62     bccno[u] = cnt;
 63     for(int i = fst[u]; ~i; i = nxt[i]){
 64         int v = vv[i];
 65         if(!bccno[v] && cut[i] == 0)
 66             dfs2(v, cnt);
 67     }
 68 }
 69 int in[N];
 70 int main(){
 71     int n, m;
 72     while(scanf("%d%d", &n, &m) != EOF){
 73         init();
 74         for(int i = 0; i < m; ++i){
 75             int u, v;
 76             scanf("%d%d", &u, &v);
 77             add(u, v), add(v, u);
 78         }
 79         dc = 0;
 80         memset(pre, 0, sizeof pre);
 81         memset(cut, 0, sizeof cut);
 82         dfs(1, -1);
 83         bcnt = 0;
 84         memset(bccno, 0, sizeof bccno);
 85         for(int i = 1; i <= n; ++i){
 86             if(!bccno[i])
 87                 dfs2(i, ++bcnt);
 88         }
 89         memset(in, 0, sizeof in);
 90         for(int i = 1; i <= n; ++i){
 91             for(int j = fst[i]; ~j; j = nxt[j]){
 92                 int v = vv[j];
 93                 if(bccno[i] == bccno[v]) continue;
 94                 in[bccno[i]]++, in[bccno[v]]++;
 95             }
 96         }
 97         int tot = 0;
 98         for(int i = 1; i <= bcnt; ++i){
 99             if(in[i] == 2) tot++;
100         }
101         printf("%d\n", (tot+1)/2);
102     }
103     return 0;
104 }

hdu 4738 Caocao‘s Bridges

有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去。

做法:找权值最小的桥。有几个坑点:图不连通,输出0;有重边;桥上的士兵数为0,输出1。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cstdio>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<set>
  9 #include<map>
 10 #include<queue>
 11 #include<bitset>
 12
 13 using namespace std;
 14
 15
 16 #pragma comment(linker, "/STACK:1024000000,1024000000")
 17 #define inf 0x3f3f3f3f
 18 #define eps 1e-9
 19 #define FOR(i,s,t) for(int i = s; i < t; ++i )
 20 #define REP(i,s,t) for( int i = s; i <= t; ++i )
 21 #define pii pair<int,int>
 22 #define MP make_pair
 23 #define ls i << 1
 24 #define rs ls | 1
 25 #define md ((ll + rr) >> 1)
 26 #define lson ll, md, ls
 27 #define rson md + 1, rr, rs
 28 #define LL  long long
 29 #define N 1010
 30 #define M 2000020
 31 #define Pi acos(-1.0)
 32 #define mod 1000007
 33 #define ULL unsigned long long
 34
 35 int fst[N], nxt[M], vv[M], cost[M], uu[M], num[N][N], e;
 36 void init(){
 37     memset(num, 0, sizeof num);
 38     memset(fst, -1, sizeof fst); e = 0;
 39 }
 40 void add(int u, int v, int c){
 41     uu[e] = u, vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;
 42 }
 43
 44 int pre[N], bccno[N], dc, bcnt;
 45 bool cut[M];
 46 int dfs(int u, int p){
 47     int lowu = pre[u] = ++dc;
 48     for(int i = fst[u]; ~i; i = nxt[i]){
 49         int v = vv[i];
 50         if(!pre[v]){
 51             int lowv = dfs(v, u);
 52             lowu = min(lowu, lowv);
 53             if(lowv > pre[u])
 54                 cut[i] = cut[i^1] = 1;
 55         }
 56         else if(v != p)
 57             lowu = min(lowu, pre[v]);
 58     }
 59     return lowu;
 60 }
 61 void dfs2(int u, int cnt){
 62     bccno[u] = cnt;
 63     for(int i = fst[u]; ~i; i = nxt[i]){
 64         int v = vv[i];
 65         if(!bccno[v] &&cut[i] == 0)
 66             dfs2(v, cnt);
 67     }
 68 }
 69 int main(){
 70     int n, m;
 71     while(scanf("%d%d", &n, &m) != EOF){
 72         if(!n && !m) break;
 73         init();
 74         for(int i = 0; i < m; ++i){
 75             int u, v,  c;
 76             scanf("%d%d%d", &u, &v, &c);
 77             add(u, v, c);
 78             add(v, u, c);
 79             num[u][v]++, num[v][u]++;
 80         }
 81         dc = 0;
 82         memset(cut, 0, sizeof cut);
 83         memset(pre, 0, sizeof pre);
 84         dfs(1, -1);
 85         bool ok = 0;
 86         for(int i = 1; i <= n; ++i){
 87             if(!pre[i]) ok = 1;
 88         }
 89         if(ok){
 90             puts("0"); continue;
 91         }
 92         bcnt = 0;
 93         memset(bccno, 0, sizeof bccno);
 94         for(int i = 1; i <= n; ++i){
 95             if(!bccno[i])
 96                 dfs2(i, ++bcnt);
 97         }
 98         //printf("bcnt %d\n", bcnt);
 99         if(bcnt == 1){
100             puts("-1"); continue;
101         }
102         int ans = inf;
103         for(int i = 0; i < e; i += 2){
104             if(cut[i] && num[uu[i]][vv[i]] == 1)
105                 ans = min(ans, cost[i]);
106         }
107         if(ans == 0) ans++;
108         printf("%d\n", ans);
109     }
110     return 0;
111 }

poj 2942 Knights of the Round Table

圆桌骑士。大白的题目。

做法:点双连通。对每个连通分量判断是不是二分图。因为二分图是没有奇圈的。如果不能够染成二分图,则有奇圈,这个连通分量的人都是能够出席的。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cstdio>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 #include<bitset>
 12 using namespace std;
 13
 14
 15 #pragma comment(linker, "/STACK:1024000000,1024000000")
 16 #define inf 0x3f3f3f3f
 17 #define eps 1e-12
 18 #define FOR(i,s,t) for(int i = s; i < t; ++i )
 19 #define REP(i,s,t) for( int i = s; i <= t; ++i )
 20 #define pii pair<int,int>
 21 #define MP make_pair
 22 #define ls i << 1
 23 #define rs ls | 1
 24 #define md ((ll + rr) >> 1)
 25 #define lson ll, md, ls
 26 #define rson md + 1, rr, rs
 27 #define LL  long long
 28 #define N 1020
 29 #define M 2000020
 30 #define Pi acos(-1.0)
 31 #define mod 1000000007
 32
 33 int fst[N], nxt[M], vv[M], e;
 34 void init(){
 35      memset(fst, -1, sizeof fst); e = 0;
 36 }
 37 void add(int u, int v){
 38     vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
 39 }
 40
 41 struct edge{
 42     int u, v;
 43     edge(int u = 0, int v = 0) : u(u), v(v) {}
 44 };
 45 stack<edge> E;
 46 vector<int> dcc[N];
 47 int pre[N], dccno[N], dc, dcnt;
 48 int dfs(int u, int p){
 49     int lowu = pre[u] = ++dc;
 50     for(int i = fst[u]; ~i; i = nxt[i]){
 51         int v = vv[i];
 52         edge e(u, v);
 53         if(!pre[v]){
 54             E.push(e);
 55             int lowv = dfs(v, u);
 56             lowu = min(lowv, lowu);
 57             if(lowv >= pre[u]){
 58                 dcnt++;
 59                 dcc[dcnt].clear();
 60                 while(1){
 61                     edge x = E.top(); E.pop();
 62                     if(dccno[x.u] != dcnt){
 63                         dcc[dcnt].push_back(x.u);
 64                         dccno[x.u] = dcnt;
 65                     }
 66                     if(dccno[x.v] != dcnt){
 67                         dcc[dcnt].push_back(x.v);
 68                         dccno[x.v] = dcnt;
 69                     }
 70                     if(x.u == u && x.v == v) break;
 71                 }
 72             }
 73         }
 74         else if(pre[v] < pre[u] && v != p)
 75             lowu = min(lowu, pre[v]);
 76     }
 77     return lowu;
 78 }
 79
 80 int col[N], odd[N];
 81 bool bipartite(int u, int p, int b){
 82     for(int i = fst[u]; ~i; i = nxt[i]){
 83         int v = vv[i];
 84         if(v == p || dccno[v] != b) continue;
 85         if(col[v] == col[u]) return 0;
 86         if(!col[v]){
 87             col[v] = 3 - col[u];
 88             if(!bipartite(v, u, b)) return 0;
 89         }
 90     }
 91     return 1;
 92 }
 93 bool g[N][N];
 94 int main(){
 95     int n, m;
 96     while(scanf("%d%d", &n, &m) != EOF){
 97         if(!n && !m) break;
 98         memset(g, 0, sizeof g);
 99         for(int i = 0; i < m; ++i){
100             int u, v;
101             scanf("%d%d", &u, &v);
102             g[u][v] = g[v][u] = 1;
103         }
104         init();
105         for(int i = 1; i <= n; ++i){
106             for(int j = i+1; j <= n; ++j){
107                 if(!g[i][j]){
108                     add(i, j), add(j, i);
109                     g[i][j] = g[j][i] = 1;
110                 }
111             }
112         }
113         dc = dcnt = 0;
114         memset(pre, 0, sizeof pre);
115         memset(dccno, 0, sizeof dccno);
116         for(int i = 1; i <= n; ++i){
117             if(!pre[i]) dfs(i, -1);
118         }
119        // printf("dcnt %d\n", dcnt);
120         memset(odd, 0, sizeof odd);
121         for(int i = 1; i <= dcnt; ++i){
122             for(int j = 0; j < dcc[i].size(); ++j) dccno[dcc[i][j]] = i;
123             memset(col, 0, sizeof col);
124             int u = dcc[i][0];
125             col[u] = 1;
126             if(!bipartite(u, -1, i))
127                 for(int j = 0; j < dcc[i].size(); ++j)
128                     odd[dcc[i][j]] = 1;
129         }
130         int ans = n;
131         for(int i = 1; i <= n; ++i)
132             if(odd[i]) ans--;
133         printf("%d\n", ans);
134     }
135 }

hdu 3394 Railway

题意:一个无向图,有 n 个景点,如果至少两个环公用一条路,路上的游客就会发生冲突;如果一条路不属于任何的环,这条路就没必要修。问,有多少路不必修,有多少路会发生冲突

做法:没必要修的路就是桥。会发生冲突,则点双连通后,若连通分量里的边数大于点数,则这个连通分量里的路都是冲突边。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cstdio>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<stack>
  9 #include<vector>
 10 #include<queue>
 11 #include<bitset>
 12
 13 using namespace std;
 14
 15
 16 #pragma comment(linker, "/STACK:1024000000,1024000000")
 17 #define inf 0x3f3f3f3f
 18 #define eps 1e-9
 19 #define FOR(i,s,t) for(int i = s; i < t; ++i )
 20 #define REP(i,s,t) for( int i = s; i <= t; ++i )
 21 #define pii pair<int,int>
 22 #define MP make_pair
 23 #define ls i << 1
 24 #define rs ls | 1
 25 #define md ((ll + rr) >> 1)
 26 #define lson ll, md, ls
 27 #define rson md + 1, rr, rs
 28 #define LL  long long
 29 #define N 10010
 30 #define M 200020
 31 #define Pi acos(-1.0)
 32 #define mod 1000007
 33 #define ULL unsigned long long
 34
 35 int fst[N], vv[M], nxt[M], e;
 36 void init(){
 37     memset(fst, -1, sizeof fst); e = 0;
 38 }
 39 void add(int u, int v){
 40     vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
 41 }
 42
 43
 44 struct edge{
 45     int u, v;
 46     edge(int u = 0, int v = 0) : u(u), v(v) {}
 47 };
 48 stack<edge> E;
 49 vector<int> dcc[N];
 50 int dccno[N], pre[N], dc, dcnt, ans1, ans2;
 51 bool in[N];
 52 void calc(vector<int> &g){
 53     memset(in, 0, sizeof in);
 54     for(int i = 0; i < g.size(); ++i)
 55         in[g[i]] = 1;
 56     int tmp = 0;
 57     for(int i = 0; i < g.size(); ++i){
 58         int u = g[i];
 59         for(int j = fst[u]; ~j; j = nxt[j]){
 60             int v = vv[j];
 61             if(in[v])
 62                 tmp++;
 63         }
 64     }
 65     tmp /= 2;
 66     if(tmp > g.size())
 67         ans2 += tmp;
 68 }
 69 int dfs(int u, int p){
 70     int lowu = pre[u] = ++dc;
 71     for(int i = fst[u]; ~i; i = nxt[i]){
 72         int v = vv[i];
 73         edge e(u, v);
 74         if(!pre[v]){
 75             E.push(e);
 76             int lowv = dfs(v, u);
 77             lowu = min(lowv, lowu);
 78             if(lowv > pre[u])
 79                 ans1++;
 80             if(lowv >= pre[u]){
 81                 dcnt++;
 82                 dcc[dcnt].clear();
 83                 while(1){
 84                     edge x = E.top(); E.pop();
 85                     if(dccno[x.u] != dcnt){
 86                         dcc[dcnt].push_back(x.u);
 87                         dccno[x.u] = dcnt;
 88                     }
 89                     if(dccno[x.v] != dcnt){
 90                         dcc[dcnt].push_back(x.v);
 91                         dccno[x.v] = dcnt;
 92                     }
 93                     if(x.u == u && x.v == v) break;
 94                 }
 95                 calc(dcc[dcnt]);
 96             }
 97         }
 98         else if(pre[v] < pre[u] && v != p)
 99             lowu = min(lowu, pre[v]);
100     }
101     return lowu;
102 }
103 int main(){
104     int n, m;
105     while(scanf("%d%d", &n, &m) != EOF){
106         if(!n && !m) break;
107         init();
108         for(int i = 0; i < m; ++i){
109             int u, v;
110             scanf("%d%d", &u, &v);
111             add(u, v), add(v, u);
112         }
113         memset(dccno, 0, sizeof dccno);
114         memset(pre, 0, sizeof pre);
115         dc = dcnt = ans1 = ans2 = 0;
116         for(int i = 0; i < n; ++i){
117             if(!pre[i])
118                 dfs(i, -1);
119         }
120         printf("%d %d\n", ans1, ans2);
121     }
122     return 0;
123 }

poj 1523 SPF

找割顶。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cstdio>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 #include<bitset>
 12 using namespace std;
 13
 14
 15 #pragma comment(linker, "/STACK:1024000000,1024000000")
 16 #define inf 0x3f3f3f3f
 17 #define eps 1e-12
 18 #define FOR(i,s,t) for(int i = s; i < t; ++i )
 19 #define REP(i,s,t) for( int i = s; i <= t; ++i )
 20 #define pii pair<int,int>
 21 #define MP make_pair
 22 #define ls i << 1
 23 #define rs ls | 1
 24 #define md ((ll + rr) >> 1)
 25 #define lson ll, md, ls
 26 #define rson md + 1, rr, rs
 27 #define LL  long long
 28 #define N 1020
 29 #define M 2000020
 30 #define Pi acos(-1.0)
 31 #define mod 1000000007
 32
 33 int fst[N], nxt[M], vv[M], e;
 34 void init(){
 35      memset(fst, -1, sizeof fst); e = 0;
 36 }
 37 void add(int u, int v){
 38     vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
 39 }
 40
 41 struct edge{
 42     int u, v;
 43     edge(int u = 0, int v = 0) : u(u), v(v) {}
 44 };
 45 stack<edge> E;
 46 vector<int> dcc[N];
 47 int pre[N], dccno[N], dc, dcnt;
 48 bool cut[N];
 49 int dfs(int u, int p){
 50     int lowu = pre[u] = ++dc;
 51     int son = 0;
 52     for(int i = fst[u]; ~i; i = nxt[i]){
 53         int v = vv[i];
 54         edge e(u, v);
 55         if(!pre[v]){
 56             E.push(e);
 57             son++;
 58             int lowv = dfs(v, u);
 59             lowu = min(lowu, lowv);
 60             if(lowv >= pre[u]){
 61                 cut[u] = 1;
 62                 ++dcnt;
 63                 dcc[dcnt].clear();
 64                 while(1){
 65                     edge x = E.top(); E.pop();
 66                     if(dccno[x.u] != dcnt){
 67                         dcc[dcnt].push_back(x.u);
 68                         dccno[x.u] = dcnt;
 69                     }
 70                     if(dccno[x.v] != dcnt){
 71                         dcc[dcnt].push_back(x.v);
 72                         dccno[x.v] = dcnt;
 73                     }
 74                     if(x.u == u && x.v == v) break;
 75                 }
 76             }
 77         }
 78         else if(pre[v] < pre[u] && v != p)
 79             lowu = min(lowu, pre[v]);
 80     }
 81     if(p < 0 && son == 1) cut[u] = 0;
 82     return lowu;
 83 }
 84 int num[N];
 85 int main(){
 86     int u, v, kk = 0;
 87     while(scanf("%d", &u) != EOF){
 88         if(u == 0) break;
 89         init();
 90         int n = u;
 91         while(1){
 92             scanf("%d", &v);
 93             n = max(n, v);
 94             add(u, v), add(v, u);
 95             scanf("%d", &u);
 96             n = max(n, u);
 97             if(u == 0) break;
 98         }
 99         memset(pre, 0, sizeof pre);
100         memset(dccno, 0, sizeof dccno);
101         memset(cut, 0, sizeof cut);
102         dc = dcnt = 0;
103         for(int i = 1; i <= n; ++i)
104             if(!pre[i])
105                 dfs(i, -1);
106        // printf("dcnt %d\n", dcnt);
107         memset(num, 0, sizeof num);
108         for(int i = 1; i <= dcnt; ++i){
109             for(int j = 0; j < dcc[i].size(); ++j)
110                 if(cut[dcc[i][j]])
111                     num[dcc[i][j]]++;
112         }
113         printf("Network #%d\n", ++kk);
114         bool ok = 0;
115         for(int i = 1; i <= n; ++i){
116             if(cut[i]){
117                 printf("  SPF node %d leaves %d subnets\n", i, num[i]);
118                 ok = 1;
119             }
120         }
121         if(!ok)  puts("  No SPF nodes");
122         puts("");
123     }
124 }

Gym 100338C Important Roads

给一个无向图。若删除某些路径,则1到n的最短路会增加,则这些路径是important的。问哪些路径是important的。

做法:对起点和终点分别求最短路,得到一定在最短路的边,然后双连通求桥。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cstdio>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<stack>
  9 #include<vector>
 10 #include<queue>
 11 #include<bitset>
 12
 13 using namespace std;
 14
 15
 16 #pragma comment(linker, "/STACK:1024000000,1024000000")
 17 #define inf 0x3f3f3f3f
 18 #define eps 1e-9
 19 #define FOR(i,s,t) for(int i = s; i < t; ++i )
 20 #define REP(i,s,t) for( int i = s; i <= t; ++i )
 21 #define pii pair<int,int>
 22 #define MP make_pair
 23 #define ls i << 1
 24 #define rs ls | 1
 25 #define md ((ll + rr) >> 1)
 26 #define lson ll, md, ls
 27 #define rson md + 1, rr, rs
 28 #define LL  long long
 29 #define N 20010
 30 #define M 200020
 31 #define Pi acos(-1.0)
 32 #define mod 1000007
 33 #define ULL unsigned long long
 34
 35 int fst[N], vv[M], nxt[M], cost[M], e;
 36 void init(){
 37     memset(fst, -1, sizeof fst); e = 0;
 38 }
 39 void add(int u, int v, int c){
 40     vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;
 41 }
 42
 43 struct edge{
 44     int v, id;
 45     edge(int v = 0, int id = 0) : v(v), id(id) {}
 46 };
 47
 48 vector<edge> g[N];
 49 bool vis[N];
 50 int d[2][N];
 51
 52 struct node{
 53     int u, dis;
 54     node(int u = 0, int dis = 0) : u(u), dis(dis) {}
 55     bool operator < (const node &b) const{
 56         return dis > b.dis;
 57     }
 58 };
 59 void dij(int s, int k){
 60     memset(vis, 0, sizeof vis);
 61     for(int i = 0; i < N; ++i)
 62         d[k][i] = (1LL<<31) - 1;
 63     priority_queue<node> q;
 64     q.push(node(s, 0));
 65     d[k][s] = 0;
 66     while(!q.empty()){
 67         node p = q.top(); q.pop();
 68         int u = p.u, dis = p.dis;
 69         if(vis[u]) continue;
 70         vis[u] = 1;
 71         for(int i = fst[u]; ~i; i = nxt[i]){
 72             int v = vv[i], c = cost[i];
 73             if(d[k][v] > d[k][u] + c){
 74                 d[k][v] = d[k][u] + c;
 75                 q.push(node(v, d[k][v]));
 76             }
 77         }
 78     }
 79 }
 80 int fa[N], id[N];
 81 void bfs(int s){
 82     queue<int> q;
 83     q.push(s);
 84     memset(fa, -1, sizeof fa);
 85     memset(vis, 0, sizeof vis);
 86     vis[s] = 1;
 87     while(!q.empty()){
 88         int u = q.front(); q.pop();
 89         for(int i = 0; i < g[u].size(); ++i){
 90             edge e = g[u][i];
 91             int v = e.v;
 92             if(!vis[v]){
 93                 fa[v] = u, id[v] = e.id;
 94                 vis[v] = 1;
 95                 q.push(v);
 96             }
 97         }
 98     }
 99 }
100 int pre[N], dc, cut[M];
101 int dfs(int u, int cot){
102     int lowu = pre[u] = ++dc;
103     for(int i = 0; i < g[u].size(); ++i){
104         edge e = g[u][i];
105         int v = e.v;
106         if(!pre[v]){
107             int lowv = dfs(v, e.id);
108             lowu = min(lowu, lowv);
109             if(lowv > pre[u])
110                 cut[e.id] = 1;
111         }
112         else if(cot != e.id)
113             lowu = min(lowu, pre[v]);
114     }
115     return lowu;
116 }
117
118 int main(){
119 //    freopen("tt.txt", "r", stdin);
120     freopen("important.in", "r", stdin);
121     freopen("important.out", "w", stdout);
122     int n, m;
123     while(scanf("%d%d", &n, &m) != EOF){
124         init();
125         for(int i = 0; i < m; ++i){
126             int u, v, c;
127             scanf("%d%d%d", &u, &v, &c);
128             add(u, v, c), add(v, u, c);
129         }
130         dij(1, 0);
131         dij(n, 1);
132         int tot = d[0][n];
133         for(int i = 1; i <= n; ++i)
134             g[i].clear();
135         for(int i = 1; i <= n; ++i){
136             for(int j = fst[i]; ~j; j = nxt[j]){
137                 int u = i, v = vv[j], c = cost[j];
138                 if(d[0][u] + c + d[1][v] == tot || d[0][v] + c + d[1][u] == tot){
139                     g[u].push_back(edge(v, j / 2));
140                     g[v].push_back(edge(u, j / 2));
141                 }
142             }
143         }
144         bfs(1);
145         dc = 0;
146         memset(cut, 0, sizeof cut);
147         memset(pre, 0, sizeof pre);
148         dfs(1, -1);
149         int u = n;
150         vector<int> ans;
151         while(u != 1){
152             if(cut[id[u]]) ans.push_back(id[u]+1);
153             u = fa[u];
154         }
155         printf("%d\n", ans.size());
156         if(ans.size() == 0){
157             puts(""); continue;
158         }
159         sort(ans.begin(), ans.end());
160         for(int i = 0; i < ans.size(); ++i)
161             printf("%d%c", ans[i], i == ans.size() - 1 ? ‘\n‘ : ‘ ‘);
162     }
163     return 0;
164 }

时间: 2024-11-03 22:23:53

双连通的相关文章

HDU 4005 The war(双连通好题)

HDU 4005 The war 题目链接 题意:给一个连通的无向图,每条边有一个炸掉的代价,现在要建一条边(你不不知道的),然后你要求一个你需要的最少代价,保证不管他建在哪,你都能炸掉使得图不连通 思路:炸肯定要炸桥,所以先双连通缩点,得到一棵树,树边是要炸的,那么找一个最小值的边,从该边的两点出发,走的路径中,把两条包含最小值的路径,的两点连边,形成一个环,这个环就保证了最低代价在里面,除了这个环以外的最小边,就是答案,这样的话,就利用一个dfs,搜到每个子树的时候进行一个维护即可 代码:

ACM学习-图双连通子图

// ACM学习-割点和桥.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> #include<vector> #include<algorithm> using namespace std; const int v = 13; int edge[v][v] = { { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0

双连通问题

一些定义: 割点集合(割集):在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合. 点连通度:最小割点集合中的顶点数. 割边集合:如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合. 边连通度:最小割边集合中的边数. 点双连通:如果一个无向连通图的点连通度大于1,则称该图是点双连通的,简称双连通或重连通.割点:一个图有割点,当且仅当这个图的点连通度为1,则割点集合的唯一元素被称为

图的连通性问题的小结 (双连通、2-SAT)

图的连通性问题包括: 1.强连通分量. 2.最小点基和最小权点基. 3.双连通. 4.全局最小割. 5.2-SAT 一.强连通分量 强连通分量很少单独出题,一般都是把求强连通分量作为缩点工具. 有三种算法: 1.Kosaraju算法.对原图和反图分别进行一次深度优先搜索. 2.Tarjan算法.用了时间戳. 3.Garbow算法.与Tarjan算法是同一思想,但更精妙. 三种算法的模版我已经贴过了  http://www.cnblogs.com/Potato-lover/p/3956604.ht

poj1515--Street Directions(边的双连通)

给一个无向图,要求变成强连通的有向图,需要保留哪些边. 边的双连通,对于桥保留两条边,其他的只保留一条边.求双连通的过程中记录保留边. /********************************************* Problem: 1515 User: G_lory Memory: 232K Time: 32MS Language: C++ Result: Accepted **********************************************/ #incl

【图论】双连通总结

双连通总结 这类问题分为,边-双连通,点-双连通 边双连通 边双连通,求出来后,连接没一个双连通的分量的就是割边,因此可以缩点成一棵树,把问题转化为在树上搞,割边的定义为:去掉这条边后图将不连通 基本这类题都一个解法,求双连通分量,然后缩点成树,进行操作 或者就是直接要求割边,做跟割边相关的操作 模板: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #

poj3352Road Construction 边双连通+伪缩点

/* 对于边双连通分支,求法更为简单.只需在求出所有的桥以后,把桥边删除,原图变成了多个连通块,则每个连通块就是一个边双连通分支.桥不属于任何 一个边双连通分支,其余的边和每个顶点都属于且只属于一个边双连通分支. 一个有桥的连通图,如何把它通过加边变成边双连通图?方法为首先求出所有的桥, 然后删除这些桥边,剩下的每个连通块都是一个双连通子图.把每个双连通子图收缩为一个顶点, 再把桥边加回来,最后的这个图一定是一棵树,边连通度为1. 统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf.则

割点、桥模板以及点双连通、边双连通

一.概念 概念: 1.桥: 如果在图G中删去一条边e后,图G的连通分支数增加,即W(G-e)>W(G),则称边u为G的桥,又称割边或关节边. 2.割点:如果在图G中删去一个结点u后,图G的连通分枝数增加,即W(G-u)>W(G),则称结点u为G的割点,又称关节点. 3.点双连通分量:不含割点的连通子图 4.边双连通分量:不含割边的连通子图 性质: 1.边双连通分量中,任意两点都在某个边环中.(任意两点不一定在点环中) 2.点双连通分量中,任意两点都在某个点环中. 3.点双连通分量不一定是边双连

poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&amp;&amp;缩点】

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 5031 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the r

POJ3352Road Construction(边的双连通+强连通缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8673   Accepted: 4330 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro