模板题——求割点与桥
题意,要使一个无向图不连通,输出必定要删掉的边的数量及其编号。求桥的裸题,可拿来练手。
套模板的时候注意本题两节点之间可能有多条边,而模板是不判重边的,所以直接套模板的话,会将重边也当做桥输出,因此要在判断桥的时候加一个判断,即当且仅当两点之间仅有一条边,且满足dfn[cur] < low[i],(cur, i)才是桥。
另外本题节点数为105,用邻接矩阵的话会内存超限,所以我用了了一个multiset存储边及其编号。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<vector> 5 #include<set> 6 #include<algorithm> 7 #include<iostream> 8 using namespace std; 9 const int MAX_V = 10005; 10 const int MAX_E = 100005; 11 struct Edge 12 { 13 int to, id; 14 Edge() {} 15 Edge(int _t, int _i):to(_t), id(_i) {} 16 bool operator < (const Edge& rhs) const 17 { 18 return to < rhs.to; 19 } 20 }; 21 multiset<Edge> edge[MAX_V]; 22 multiset<int> tms[MAX_V]; 23 vector<int> ans; 24 int vis[MAX_V]; //结点v当前访问状态,0表示未访问,1表示在栈中,2表示已经访问过 25 int dfn[MAX_V]; //结点v被访问时的深度 26 int low[MAX_V]; //结点v可以到达的访问时间最早的祖先的深度 27 void cut_bridge(int cur, int father, int dep, int n) //vertex: 0~n-1 28 { 29 vis[cur] = 1; 30 dfn[cur] = dep; 31 low[cur] = dep; 32 int children = 0; 33 int sz = edge[cur].size(); 34 for(multiset<Edge>::iterator it = edge[cur].begin(); it != edge[cur].end(); it++) 35 { 36 int id = (*it).id; 37 int i = (*it).to; 38 if(i != father && vis[i] == 1) //i在当前栈中,说明图中有一个环,用i的深度更新cur的low值; 39 { 40 if(dfn[i] < low[cur]) low[cur] = dfn[i]; //将结点cur可以到达的访问时间最早的祖先的深度更新为结点i被访问时的深度; 41 } 42 if(vis[i] == 0) //i没被访问过,递归访问节点i,并用i的可以到达的最早祖先来更新cur的low值; 43 { 44 cut_bridge(i, cur, dep+1, n); 45 if(low[i] < low[cur]) low[cur] = low[i]; 46 if(low[i] > dfn[cur] && tms[cur].count(i) == 1) 47 { 48 ans.push_back(id); 49 }//判断桥 50 } 51 } 52 vis[cur] = 2; 53 } 54 void init(int n) 55 { 56 ans.clear(); 57 memset(vis, 0, sizeof(vis)); 58 for(int i = 0; i <= n; i++) 59 { 60 edge[i].clear(); 61 tms[i].clear(); 62 } 63 } 64 int main() 65 { 66 int T; 67 scanf("%d", &T); 68 for(int kase = 0; kase < T; kase++) 69 { 70 if(kase) printf("\n"); 71 int n, m; 72 scanf("%d%d", &n, &m); 73 init(n); 74 for(int i = 0; i < m; i++) 75 { 76 int u, v; 77 scanf("%d%d", &u, &v); 78 Edge e1(v, i+1), e2(u, i+1); 79 edge[u].insert(e1); 80 edge[v].insert(e2); 81 tms[u].insert(v); 82 tms[v].insert(u); 83 } 84 for(int i = 1; i <= n; i++) 85 if(vis[i] == 0) 86 cut_bridge(i, -1, 1, n); 87 88 sort(ans.begin(), ans.end()); 89 printf("%d\n", ans.size()); 90 for(int i = 0; i < ans.size(); i++) 91 { 92 if(i) printf(" "); 93 printf("%d", ans[i]); 94 } 95 if(ans.size()) printf("\n"); 96 } 97 return 0; 98 }
【求无向图的桥,有重边】ZOJ - 2588 Burning Bridges
原文:http://www.cnblogs.com/LLGemini/p/4730961.html