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

你可能感兴趣的:(sort)