RT,整理了一个Tarjan求割点(边)的模板,和以往不同的是记录了两条边的idx,遇到相同idx的回边不会再走。这样有重边就不会误判成割点(边)了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Edge { 5 int u, v, next; 6 int id; 7 bool bridge; 8 }Edge; 9 10 const int maxn = 100100; 11 const int maxm = 200100; 12 int dfn[maxn], low[maxn], vis[maxn]; 13 int head[maxn]; 14 bool cut[maxn]; 15 Edge edge[maxm]; 16 int n, m, rt, ecnt; 17 int dcnt; 18 19 void init() { 20 memset(head, -1, sizeof(head)); 21 memset(dfn, 0, sizeof(dfn)); 22 memset(vis, 0, sizeof(vis)); 23 memset(low, 0, sizeof(low)); 24 memset(cut, 0, sizeof(cut)); 25 dcnt = ecnt = 0; 26 } 27 28 void adde(int u, int v, int id) { 29 edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].id = id; 30 edge[ecnt].bridge = 0; 31 edge[ecnt].next = head[u]; 32 head[u] = ecnt++; 33 } 34 35 void dfs(int u, int id) { 36 dfn[u] = low[u] = ++dcnt; 37 vis[u] = 1; 38 int son = 0; 39 for(int i = head[u]; ~i; i=edge[i].next) { 40 int v = edge[i].v; 41 if(id == edge[i].id) continue; 42 if(!vis[v]) { 43 dfs(v, edge[i].id); son++; 44 low[u] = min(low[u], low[v]); 45 if((rt == u && son >= 2) || (rt != u && low[v] >= dfn[u])) { 46 cut[u] = 1; 47 } 48 if(low[v] > dfn[u]) { 49 edge[i].bridge = edge[i^1].bridge = 1; 50 } 51 } else { 52 low[u] = min(low[u], dfn[v]); 53 } 54 } 55 } 56 57 int main() { 58 freopen("in", "r", stdin); 59 int u, v; 60 while(~scanf("%d%d",&n,&m)) { 61 init(); 62 for(int i = 0; i < m; i++) { 63 scanf("%d%d",&u,&v); 64 adde(u, v, i); adde(v, u, i); 65 } 66 rt = 1; 67 dfs(rt, -1); 68 printf("Bridge: "); 69 for(int i = 0; i < ecnt; i++) { 70 if(edge[i].bridge) { 71 printf("%d %d\n", edge[i].u, edge[i].v); 72 } 73 } 74 puts(""); 75 for(int i = 1; i <= n; i++) printf("%d ", cut[i]); 76 puts(""); 77 for(int i = 1; i <= n; i++) printf("%d ", dfn[i]); 78 puts(""); 79 for(int i = 1; i <= n; i++) printf("%d ", low[i]); 80 puts(""); 81 } 82 return 0; 83 }