POJ 2762 Going from u to v or from v to u?(强连通+缩点+拓扑排序)

Going from u to v or from v to u?

 

Description

In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?

Input

The first line contains a single integer T, the number of test cases. And followed T cases. 

The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly. 

Output

The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.

Sample Input

1
3 3
1 2
2 3
3 1

Sample Output

Yes

  1 #include<cstdio>
  2 #include<vector>
  3 #include<queue>
  4 #include<stack>
  5 #include<algorithm>
  6 #include<cstring>
  7 using namespace std;
  8 
  9 vector<int>G[1005];
 10 vector<int>G1[1005];
 11 stack<int>s;
 12 int dfn[1005],lowlink[1005],sccno[1005],in[1005];
 13 int m,n,dfs_clock,scc_cnt;
 14 bool ok;
 15 
 16 void init()
 17 {
 18     memset(dfn,0,sizeof(dfn));
 19     memset(lowlink,0,sizeof(lowlink));
 20     memset(sccno,0,sizeof(sccno));
 21     memset(in,0,sizeof(in));
 22     for(int i=0;i<n;i++)G[i].clear(),G1[i].clear();
 23     dfs_clock=scc_cnt=0;
 24 }
 25 
 26 void tarjan(int u)
 27 {
 28     lowlink[u]=dfn[u]=++dfs_clock;
 29     s.push(u);
 30     for(int i=0;i<G[u].size();i++)
 31     {
 32         int v=G[u][i];
 33         if(!dfn[v])
 34         {
 35             tarjan(v);
 36             lowlink[u]=min(lowlink[u],lowlink[v]);
 37         }
 38         else if(!sccno[v])
 39             lowlink[u]=min(lowlink[u],dfn[v]);
 40     }
 41     if(lowlink[u]==dfn[u])
 42     {
 43         scc_cnt++;
 44         while(1)
 45         {
 46             int x=s.top();
 47             s.pop();
 48             sccno[x]=scc_cnt;
 49             if(x==u)break;
 50         }
 51     }
 52 }
 53 
 54 void toposort()
 55 {
 56     ok=1;
 57     int sum=0;
 58     queue<int>q;
 59     for(int i=1;i<=scc_cnt;i++)
 60         if(in[i]==0)
 61             q.push(i);
 62     while(!q.empty())
 63     {
 64         if(q.size()!=1)
 65         {
 66             ok=0;
 67             return;
 68         }
 69         int x=q.front();
 70         q.pop();
 71         sum++;
 72         for(int i=0;i<G1[x].size();i++)
 73             if(--in[G1[x][i]]==0)
 74                 q.push(G1[x][i]);
 75     }
 76     if(sum!=scc_cnt)
 77     {
 78         ok=0;
 79         return;
 80     }
 81 }
 82 
 83 int main()
 84 {
 85     int T;
 86     scanf("%d",&T);
 87     while(T--)
 88     {
 89         init();
 90         scanf("%d%d",&n,&m);
 91         for(int i=0;i<m;i++)
 92         {
 93             int u,v;
 94             scanf("%d%d",&u,&v);
 95             G[u].push_back(v);
 96         }
 97         for(int i=1;i<=n;i++)
 98             if(!dfn[i])
 99                 tarjan(i);
100         for(int i=1;i<=n;i++)
101             for(int j=0;j<G[i].size();j++)
102             {
103                 int v=G[i][j];
104                 if(sccno[i]!=sccno[v])
105                 {
106                     G1[sccno[i]].push_back(sccno[v]);
107                     in[sccno[v]]++;
108                 }
109             }
110         toposort();
111         ok?puts("Yes"):puts("No");
112     }
113     return 0;
114 }

 



posted on 2015-10-08 11:12    阅读(297)  评论(0编辑  收藏  举报

导航