图的单向连通

 

poj 2762

  题意:任给一个图,问你对于任意的两个点x,y之间是否存在从x到y或从y到x的路径?

  分析:这显然是要求图是否为单向连通图?我们可以对强连通分量进行缩点,缩点后的图一定是一个有向无环图; 现在,问题等价于给你一个有向无环图,问你它是否为单向连通图。这样,我们就可以对有向无环图进行拓扑排序,当且仅当得到的拓扑序列中任意相邻两点间边连通,即topo[i]--topo[i+1]之间存在边时,有向无环图是单向连通图。

 

  

  1 #include<cstdio>

  2 #include<cstring>

  3 #include<queue>

  4 #include<algorithm>

  5 #define _Clr(x, y) memset(x, y, sizeof(x))

  6 #define INF 0x3f3f3f3f

  7 #define N 1010

  8 using namespace std;

  9 

 10 struct Node

 11 {

 12     int to, next;

 13 }edge[N*6];

 14 int head[N], tot;

 15 int dfn[N], low[N];

 16 int bleg[N], Sta[N];

 17 bool instack[N];

 18 int cnt, top, ght, n;

 19 

 20 void Init()

 21 {

 22     cnt=tot=ght=top=0;

 23     _Clr(head, -1);

 24     _Clr(dfn, 0);

 25     _Clr(instack, 0);

 26 }

 27 

 28 void Add_edge(int a, int b)

 29 {

 30     edge[tot].to = b;

 31     edge[tot].next = head[a];

 32     head[a] = tot++;

 33 }

 34 

 35 void dfs(int u)

 36 {

 37     dfn[u]=low[u]=++cnt;

 38     Sta[top++] = u;

 39     instack[u] = true;

 40     for(int i=head[u]; i!=-1; i=edge[i].next)

 41     {

 42         int v = edge[i].to;

 43         if(!dfn[v])

 44         {

 45             dfs(v);

 46             low[u] = min(low[u], low[v]);

 47         }

 48         else if(instack[v]) low[u] = min(low[u], dfn[v]);

 49     }

 50     if(low[u]==dfn[u])

 51     {

 52         ght++;

 53     //    printf("Num: %d\n",ght);

 54         int v;

 55         do

 56         {

 57             v = Sta[--top];

 58       //      printf("%d ",  v);

 59             instack[v] = false;

 60             bleg[v] = ght;

 61         }while(u!=v);

 62     //    puts("");

 63     }

 64 }

 65 

 66 int inde[N], mat[N][N];

 67 void Tarjan()

 68 {

 69     for(int i=1; i<=n; i++)

 70         if(!dfn[i]) dfs(i);

 71 

 72     _Clr(inde, 0);

 73     _Clr(mat, 0);

 74     // 缩点建立新的有向无环图并且求每个点的入度

 75     for(int u=1; u<=n; u++)

 76     for(int i=head[u]; i!=-1; i=edge[i].next)

 77     {

 78         int v = edge[i].to;

 79         if(bleg[v] != bleg[u])

 80         {

 81             inde[bleg[v]]++;

 82             mat[bleg[u]][bleg[v]] = 1;

 83         }

 84     }

 85 }

 86 

 87 int topo[N], k=0;

 88 void TopSort()

 89 {

 90     queue<int> Q;

 91     for(int i=1; i<=ght; i++)

 92         if(inde[i]==0) Q.push(i);

 93   //  printf("TopSort: \n");

 94     k=0;

 95     while(!Q.empty())

 96     {

 97         int u = Q.front(); Q.pop();

 98     //    printf("%d ", u);

 99         topo[++k] = u;

100         for(int i=1; i<=ght; i++)

101         {

102             if(!mat[u][i]) continue;

103             inde[i]--;

104             if(inde[i]==0) Q.push(i);

105         }

106     }

107    // puts("");

108 }

109 

110 void Solved()

111 {

112     bool tag = true;

113   //  printf("k=%d\n", k);

114     for(int i=1; i<k; i++)

115         if(!mat[topo[i]][topo[i+1]])    //若拓扑序列存在两个相邻的点之间不连通则非单向连通图

116         {

117             tag = false;

118             break;

119         }

120     puts(tag ? "Yes" : "No");

121 }

122 

123 int main()

124 {

125     int T, m, a, b;

126     scanf("%d", &T);

127     while(T--)

128     {

129         Init();

130         scanf("%d%d", &n, &m);

131         while(m--)

132         {

133             scanf("%d%d",&a, &b);

134             Add_edge(a, b);

135         }

136         Tarjan();

137         TopSort();

138         Solved();

139     }

140     return 0;

141 }
View Code

 

你可能感兴趣的:(图)