Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 15812 | Accepted: 4194 |
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题目大意:n个节点 m条单向边。构成一个图,问你是否可以保证任选2个点u、v,这两个点之间是连通的? 保证则输出:Yes 否则:No强连通分量算法将图化简缩点后,进行拓扑排序。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <vector> #include <stack> #include <algorithm> #define N 1002 using namespace std; struct node { int e, val; }item; vector<node>g[N]; stack<int>st; int dfn[N], low[N]; int id[N]; //标记i节点属于哪个连通分量 int mat2[N][N]; int n2; int counter, n, scnt; void Tarjan(int e) { int t, i; int mm=low[e]=dfn[e]=counter++; st.push(e);//入栈 for(i=0; i<g[e].size(); i++){ t=g[e][i].e; if(dfn[t]==-1) Tarjan(t); if(low[t]<mm) mm=low[t]; } if(mm<low[e]){//有回边 low[e]=mm; return; } do{ id[t=st.top()]=scnt; low[t]=n; st.pop(); }while(t!=e); scnt++; } void Search(int n) { int i; memset(dfn, -1, sizeof(dfn)); counter=0; scnt=0; for(i=0; i<n; i++) if(dfn[i]==-1) Tarjan(i); } void base_vertex() { int i, j, t; Search(n); //调用求强连通分量 n2=scnt; memset(mat2,0,sizeof(mat2)); for(i=0; i<n; i++){ for(j=0; j<g[i].size(); j++){ t=g[i][j].e; mat2[id[i]][id[t]]=1; } } } int topo_sort(int n, int mat[][N], int *topo) {//拓扑排序的n是强连通分量的个数 int d[N], i, j, k; for(i=0; i<n; i++){ d[i]=0; for(j=0; j<n; j++) d[i]=d[i]+mat[j][i];//入度数 } for(k=0; k<n; k++){ for(i=0; d[i]&&i<n; i++); if(i==n) return 0; d[i]=-1; for(j=0; j<n; j++) d[j]-=mat[i][j]; topo[k]=i; } return 1; } int main() { int tg; scanf("%d", &tg); int m, u, v; int i, j; int topo[N]; while(tg--) { scanf("%d %d", &n, &m); for(i=0; i<=n; i++) g[i].clear(); for(i=0; i<m; i++){ scanf("%d %d", &u, &v); item.e=v-1; item.val=1; g[u-1].push_back(item); }//建立单向图 base_vertex(); topo_sort(n2, mat2, topo); int flag=1; for(i=0; i<n2-1; i++){ if(!mat2[topo[i]][topo[i+1]] ){ flag=0; break; } } if(flag) printf("Yes\n"); else printf("No\n"); } return 0; } /* 下面的数据会访问冲突崩溃掉 但poj可以Accepted 不懂~~~ 1 8 11 1 2 2 3 2 5 2 6 3 5 4 3 5 2 5 4 6 7 6 8 7 6 */