强连通图 Tarjan算法

算法学习: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 0
Sample 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;
    }
}
当初的梦想实现了吗,事到如今只好放弃吗~
原文地址:https://www.cnblogs.com/caijiaming/p/9389108.html