码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1269 有向图强连通 【Targan】(模板)

时间:2018-08-16 21:34:34      阅读:689      评论:0      收藏:0      [点我收藏+]

标签:ems   ==   标记   dfs   底部   链式前向星   链式   有向图   sample   

<题目链接>

题目大意:

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

解题分析:
有向图求强连通分量的裸题,下面用的是Targan算法。

#include <cstdio>
#include <cstring>

const int maxn=100000+100;

struct EDGE{
    int next;
    int to;
}edge[maxn];

int n,m,cnt,top,sumlink;
int head[maxn];
int dfn[maxn];
int vis[maxn],Stack[maxn];
int low[maxn];

int min(int a,int b){return a<b?a:b;}

void add(int u,int v){      //链式前向星构图
    edge[++cnt].next=head[u];
    edge[cnt].to=v;
    head[u]=cnt;
}

void INIT(){        //初始化
    memset(dfn,0,sizeof(dfn));
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    cnt=0;      //遍历的时间坐标
    top=0;      //栈中的元素个数
    sumlink=0;  //连通分量的个数
}

void Targan(int u){
    if(sumlink>1)return;       //如果连通分量>1,说明不符合题意,直接结束
    dfn[u]=low[u]=++cnt;    //dfn为遍历的序号
    Stack[++top]=u;         //入栈
    vis[u]=true;          //标记该点在栈里

    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(!dfn[v]){       //如果这个点没有遍历过
            Targan(v);        
            low[u]=min(low[u],low[v]);        
        }        
        else if(vis[v]){    //如果这个点在栈中        
            low[u]=min(low[u],dfn[v]);         
        }
    }

    if(dfn[u]==low[u]){     //如果找到了这个连通分量的根节点
        sumlink++;       //连通分量数量+1
        while(true){
            int temp=Stack[top];
            vis[temp]=0;
            --top;          //及时将该连通块在栈中的点排出,配合vis[]数组,能够使同一连通块的low值相同,而不是这个联通块的值等于它之前遍历到的连通块的low值
            if(temp==u)     //将该连通块中的根节点搜索完后(根节点==该连通块最早被dfs到的点==该连通块在栈的最底部的点)
                break;
        }
    }
}


int main(){
    while(scanf("%d %d",&n,&m)!=EOF,n|m){
        INIT();
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i])
                Targan(i);
        }

        if(sumlink==1){
            printf("Yes\n");
        }
        else
            printf("No\n");
    }
    return 0;
}



2018-08-16

hdu1269 有向图强连通 【Targan】(模板)

标签:ems   ==   标记   dfs   底部   链式前向星   链式   有向图   sample   

原文地址:https://www.cnblogs.com/00isok/p/9489930.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!