算法学习:https://blog.csdn.net/qq_16234613/article/details/77431043
http://www.cnblogs.com/chenchengxun/p/4718698.html
题目链接:https://vjudge.net/contest/219056#problem/B
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。
Input输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。
Output对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。
Sample Input
3 3 1 2 2 3 3 1 3 3 1 2 2 3 3 2 0 0Sample Output
Yes No
个人思路:就是强连通图的裸题吧,学了就能过了,上面两篇博客看了应该没什么问题了
看代码:
#include<iostream> #include<cstdio> #include<cstring> #include<stdio.h> #include<string.h> #include<cmath> #include<math.h> #include<algorithm> #include<set> #include<queue> #include<map> typedef long long ll; using namespace std; const ll mod=1e9+7; const int maxn=1e4+10; const int maxk=100+10; const int maxx=1e4+10; const ll maxe=1000+10; #define INF 0x3f3f3f3f3f3f int n,m,time=1,top,sum,block; int dfn[maxn],low[maxn];//dfn存储到该点的时间,low存储从该点能到达的最小序号 int Stack[maxn];//自定义栈 int instack[maxn];//instack判断是否入栈 vector<int> G[maxn]; void init() { memset(instack,0,sizeof(instack)); memset(Stack,0,sizeof(Stack)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); for(int i=0;i<=n;i++) G[i].clear(); } void solve(int u) { low[u]=dfn[u]=time++;//初始化为到该点的时间 Stack[top++]=u;//把u入栈 instack[u]=1;//标记已经入栈 int v; for(int i=0;i<G[u].size();i++) { v=G[u][i]; if(dfn[v]==0)//还没有访问过 { solve(v); low[u]=min(low[u],low[v]); } else if(instack[v])//已经访问过,并且入栈 low[u]=min(low[u],low[v]); } if(low[u]==dfn[u])//相等时代表有环,但是Tarjan算法一个点也被看作环 { int m=Stack[--top]; while(m!=u) { sum++; m=Stack[--top]; } sum++;//加上本身 block++;//这里是记录有多少个块,只能有一个块把所有的点都连成一个强连通图 } } int main() { while(cin>>n>>m) { if(n==0&&m==0) break; sum=0; top=0; time=1; block=0; init(); int u,v; for(int i=0;i<m;i++) { cin>>u>>v; G[u].push_back(v); } solve(1); // cout<<sum<<" "<<block<<endl; if(block==1&&sum==n) cout<<"Yes"<<endl; else cout<<"No"<<endl; } }