hdu1269 迷宫城堡 (强连通模板)(有向图)

来源:互联网 发布:宾格手表 知乎 编辑:程序博客网 时间:2024/04/30 17:47
///题意当强连通分量为1的时候输出Yes否者输出No。 两两可达# include<stdio.h># include<algorithm># include<stack># include<vector># include<string.h>using namespace std;# define MAXN 10005 ///题目中可能的最大点数# define MAXM 100005 ///边数struct Edge{    int v,next;} edge[MAXM]; ///边结点数组      边int first[MAXN],Stack[MAXN],DFN[MAXN],Low[MAXN],Belong[MAXM];///边///first[]头结点数组  stack[]为栈  DFN[]为深度优先搜索次序数组///Belong[]为每个结点所对应的强连通分量标号数组///Low[u]为u结点的子树结点所能追溯到的最早栈中的标记数组int instack[MAXN];///是否在栈中的标记数组int n,m,cnt,scnt,top,tot;void init(){    cnt=0;    scnt=top=tot=0;///初始化连通分量标号,栈顶指针,次序计数器为0    memset(first,-1,sizeof(first));    memset(DFN,0,sizeof(DFN));///结点搜素的次序编号数组为0,同时可以当作是否访问的数组使用}void read_graph(int u,int v)///构建邻接表{    edge[tot].v=v;    edge[tot].next=first[u];    first[u]=tot++;}void Tarjan(int v){    int min,t;    DFN[v]=Low[v]=++tot; ///cnt为时间戳    instack[v]=1;///标记在栈中    Stack[top++]=v;///入栈    for(int e=first[v];e!=-1;e=edge[e].next)    {///枚举每一条边        int j=edge[e].v; ///v所邻接的边        if(!DFN[j])///未被访问        {            Tarjan(j);///继续往下找            if(Low[v]>Low[j])                Low[v]=Low[j];///更新结点v到所能到达的最小次数层        }        else if(instack[j]&&DFN[j]<Low[v])        {//如果j结点在栈内            Low[v]=DFN[j];        }    }    if(DFN[v]==Low[v])    {///如果结点v是强连通分量的根        scnt++;///连通分量+1        do        {            t=Stack[--top];///退栈            instack[t]=0;///标记不在栈中            Belong[t]=scnt;///出栈结点t属于cnt标号的强连通分量        }while(t!=v);///知道将v从栈中退出    }}void slove(){    for(int i=1;i<=n;i++)///枚举每个结点,搜索连通分量        if(!DFN[i])///未被访问        Tarjan(i);///则找i结点的连通分量}int main(){    while(~scanf("%d%d",&n,&m),n+m)    {        init();        for(int i=1; i<=m; i++)        {            int a,b;            scanf("%d%d",&a,&b);            read_graph(a,b);        }        slove();///求强连通分量        if(scnt==1)///只有一个强连通分量,所以两两都可到达            printf("Yes\n");        else            printf("No\n");    }    return 0;}

0 0