迷宫城堡(有向图的强联通分量)

迷宫城堡
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 19906    Accepted Submission(s): 8688






Problem Description


为了训练小希的方向感,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

强连通(strongly connected): 在一个有向图G里,设两个点 a b 发现,由a有一条路可以走到b,由b又有一条路可以走到a,我们就叫这两个顶点(a,b)强连通。

强连通图: 如果 在一个有向图G中,每两个点都强连通,我们就叫这个图,强连通图。

强连通分量strongly connected components):在一个有向图G中,有一个子图,这个子图每2个点都满足强连通,我们就叫这个子图叫做 强连通分量 [分量::把一个向量分解成几个方向的向量的和,那些方向上的向量就叫做该向量(未分解前的向量)的分量]

Tarjan:


#include<map>
#include<stack>
#include<queue>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define maxn 10005
#define maxm 100005
#define ll long long
#define inf 0x3f3f3f
using namespace std;
struct edge{
    int to,next;
}edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],stac[maxn],belong[maxn];
int index,top;
int scc;
bool instack[maxn];
int num[maxn];
void addedge(int u,int v){
    edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void Tarjan(int u){
    int v;
    low[u]=dfn[u]=++index;
    stac[top++]=u;
    instack[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(!dfn[v]){
            Tarjan(v);
            if(low[u]>low[v])low[u]=low[v];
        }
        else if(instack[v]&&low[u]>dfn[v])
            low[u]=dfn[v];
    }if(low[u]==dfn[u]){
        scc++;
        do{
            v=stac[--top];
            instack[v]=false;
            belong[v]=scc;
            num[scc]++;
        }while(v!=u);
    }
}
void solve(int n){
    memset(dfn,0,sizeof(dfn));
    memset(instack,false,sizeof(instack));
    memset(num,0,sizeof(num));
    index=scc=top=0;
    for(int i=1;i<=n;i++){
        if(!dfn[i])Tarjan(i);
    }
}
void init(){
    tot=0;
    memset(head,-1,sizeof(head));
}
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0)break;
        init();
        for(int i=0;i<m;i++){
            int a,b;scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        solve(n);
        if(scc==1)printf("Yes
");
        else printf("No
");
    }
}




 

原文地址:https://www.cnblogs.com/da-mei/p/9053251.html