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 }

 

 

题目链接:http://poj.org/problem?id=2762

posted @ 2012-10-03 21:33  Griselda.  阅读(182)  评论(0编辑  收藏  举报