POJ 2762 强连通分量中存在单相连通边 【tarjan+toposort+缩点】.cpp
题意:
给出一些房间之间的关系
问任意两个房间是否存在一条互通的路径..即单相连通..
输入:
给出T表示有T组数据
每组数据给出n m 表示n个房间 m个关系
接下来m行..每行给出a b 表示a房间 和 b房间之间是连通的..
如果任意两个房间之间存在单相连通..则输出yes 否则 no
思路:
先用tarjan算法求出每个强连通分量..然后对每一个进行染色..
然后建图..拓扑排序..
如果排序不唯一..就是有超过两个点是有0个初度的..
这代表其中有两个房间是不相连的..
Tips:
点太多或者边太多的情况下..
就要用前向星建图了..
Code:
View Code
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define clr(x) memset(x, 0, sizeof(x)) 6 const int INF = 0x1f1f1f1f; 7 const int MAXN = 1010; 8 9 int n, m; 10 11 struct Edge 12 { 13 int to; 14 int next; 15 }edge[1000010], edge2[1000010]; 16 int head[MAXN], head2[MAXN]; 17 int tot, tot2; 18 19 void add(int s, int u) 20 { 21 edge[tot].to = u; 22 edge[tot].next = head[s]; 23 head[s] = tot++; 24 } 25 26 void add2(int s, int u) 27 { 28 edge2[tot2].to = u; 29 edge2[tot2].next = head2[s]; 30 head2[s] = tot2++; 31 } 32 33 int ti, top, cnt; 34 int dfn[MAXN], low[MAXN], ins[MAXN]; 35 int col[MAXN], sta[MAXN]; 36 37 void tarjan(int u) 38 { 39 int i, k; 40 dfn[u] = low[u] = ++ti; 41 sta[++top] = u; 42 ins[u] = 1; 43 for(i = head[u]; i != -1; i = edge[i].next) { 44 k = edge[i].to; 45 if(dfn[k] == 0) { 46 tarjan(k); 47 low[u] = min(low[u], low[k]); 48 } 49 else if(ins[k]) { 50 low[u] = min(low[u], dfn[k]); 51 } 52 } 53 54 if(dfn[u] == low[u]) { 55 ++cnt; 56 do 57 { 58 k = sta[top--]; 59 col[k] = cnt; 60 ins[k] = 0; 61 }while(k != u); 62 } 63 } 64 65 void solve_ta() 66 { 67 ti = top = cnt = 0; 68 clr(dfn), clr(ins); 69 for(int i = 1; i <= n; ++i) 70 if(!dfn[i]) 71 tarjan(i); 72 } 73 74 int ind[MAXN]; 75 int q[MAXN]; 76 int v[MAXN]; 77 int f1, f2, num; 78 79 void make_G() 80 { 81 int i, j, k; 82 tot2 = 0; 83 memset(head2, 0xff, sizeof(head2)); 84 85 solve_ta(); 86 for(i = 1; i <= n; ++i) 87 for(j = head[i]; j != -1; j = edge[j].next) { 88 k = edge[j].to; 89 if(col[i] != col[k]) { 90 add2(col[i], col[k]); 91 ind[col[k]]++; 92 } 93 } 94 } 95 96 void toposort() 97 { 98 int front = 0, rear = 0; 99 int i, k; 100 f1 = 1, f2 = 0; 101 clr(ind); 102 make_G(); 103 104 for(i = 1; i <= cnt; i++) 105 if(ind[i] == 0) 106 q[rear++] = i; 107 if(rear > 1) 108 f1 = -1; 109 num = 0; 110 while(front < rear) { 111 int x = q[front++]; 112 int tt = 0; 113 num++; 114 for(i = head2[x]; i!=-1; i = edge2[i].next) { 115 k = edge2[i].to; 116 ind[k]--; 117 if(ind[k] == 0) { 118 q[rear++] = k; 119 tt++; 120 } 121 } 122 if(tt > 1) 123 f2 = -1; 124 } 125 } 126 int main() 127 { 128 int i, j, k; 129 int T; 130 int a, b; 131 bool flag; 132 while(scanf("%d", &T) != EOF) 133 while(T--) 134 { 135 tot = 0; 136 memset(head, 0xff, sizeof(head)); 137 flag = true; 138 139 scanf("%d %d", &n, &m); 140 while(m--) { 141 scanf("%d %d", &a, &b); 142 add(a, b); 143 } 144 145 toposort(); 146 if(f1 == -1 || f2 == -1 || num != cnt) flag = false; 147 148 if(flag) puts("Yes"); 149 else puts("No"); 150 } 151 return 0; 152 }