题目链接:
题目描述:
题目中给出一个有可能不连通的无向图,求出这个图的桥,并且把桥按照起点升序输出(还有啊,还有啊,每个桥的起点要比终点靠前啊),这个题目读了好几遍,但是依旧没有找到数据范围写在哪里,经过无数次runtime error最终把范围定在1W左右。(题目晦涩难懂,wa到死了,嗷~~~~~~)
解题思路:
就是用Tarjan算法dfs出low和dfn数组,然后记录下来起点和终点排好序的桥,然后把桥排序输出就ok了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 11000; 8 struct node 9 { 10 int to, next; 11 } edge[maxn*10]; 12 bool cmp (node a, node b) 13 { 14 if (a.next == b.next) 15 return a.to < b.to; 16 return a.next < b.next; 17 } 18 int low[maxn], dfn[maxn], head[maxn]; 19 int Father[maxn], tot, ntime, cnt; 20 node Q[maxn * 10]; 21 void init () 22 { 23 ntime = tot = cnt = 0; 24 memset (low, 0, sizeof(low)); 25 memset (dfn, 0, sizeof(dfn)); 26 memset (head, -1, sizeof(head)); 27 memset (Father, 0, sizeof(Father)); 28 } 29 void Add (int from, int to) 30 { 31 edge[tot].to = to; 32 edge[tot].next = head[from]; 33 head[from] = tot ++; 34 } 35 void Tarjan (int u, int father) 36 { 37 low[u] = dfn[u] = ++ntime; 38 Father[u] = father; 39 for (int i=head[u]; i!=-1; i=edge[i].next) 40 { 41 int v = edge[i].to; 42 if (!dfn[v]) 43 { 44 Tarjan (v, u); 45 low[u] = min (low[u], low[v]); 46 } 47 else if (father != v) 48 low[u] = min (low[u], dfn[v]); 49 } 50 } 51 int main () 52 { 53 int n, m; 54 node q; 55 while (scanf ("%d", &n) != EOF) 56 { 57 init (); 58 m = n; 59 while (n --) 60 { 61 int u , k; 62 scanf ("%d (%d)", &u, &k); 63 while (k --) 64 { 65 int v; 66 scanf ("%d", &v); 67 Add (u, v); 68 Add (v, u); 69 } 70 } 71 for (int i=0; i<m; i++) 72 if (!dfn[i]) 73 Tarjan (i, -1); 74 75 for (int i=0; i<m; i++) 76 { 77 int v = Father[i]; 78 if (v != -1 && dfn[v] < low[i]) 79 { 80 q.next = v; 81 q.to = i; 82 if (q.next > q.to) 83 swap(q.next, q.to); 84 Q[cnt++] = q; 85 } 86 } 87 printf ("%d critical links ", cnt); 88 sort (Q, Q+cnt, cmp); 89 for (int i=0; i<cnt; i++) 90 printf ("%d - %d ", Q[i].next, Q[i].to); 91 printf (" "); 92 } 93 return 0; 94 }