HDU 1269 迷宫城堡(Tarjan or Kosaraju模板)

来源:互联网 发布:数据录入兼职平台 编辑:程序博客网 时间:2024/06/05 23:59

迷宫城堡

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 17917 Accepted Submission(s): 7852

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

Author
Gardon

Source
HDU 2006-4 Programming Contest

Recommend
lxj

用来试试自己写的模板

Tarjan:

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <vector>#define maxn 10010using namespace std;int vis[maxn];int dfn[maxn];int low[maxn];int s[maxn];int dfncnt=0;int top=0;int cnt=0;int col[maxn];int colcnt=0;int head[maxn];struct node{    int to,next;}e[100010];void tarjan(int x){    dfn[x]=++cnt;    vis[x]=1;    low[x]=dfn[x];    s[top++]=x;    for(int i=head[x];i!=-1;i=e[i].next)    {        int to=e[i].to;        if(!dfn[to])        {            tarjan(to);            low[x]=min(low[x],low[to]);        }        else if(vis[to]) low[x]=min(low[x],dfn[to]);    }    if(low[x]==dfn[x])    {        col[x]=++colcnt;        vis[x]=0;        while(s[top-1]!=x)        {            vis[s[top-1]]=0;            col[s[top-1]]=colcnt;            top--;        }        top--;    }}void add(int a,int b){    e[cnt].to=b;    e[cnt].next=head[a];    head[a]=cnt++;}void init(int n){    memset(vis,0,sizeof(vis));    memset(s,0,sizeof(s));    memset(head,-1,sizeof(head));    memset(col,0,sizeof(col));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    cnt=0;    top=0;    dfncnt=0;    colcnt=0;}int main(){    int m,n;    int a,b;    while(scanf("%d%d",&n,&m)==2)    {        if(m==0&&n==0)break;        init(n);        for(int i=0;i<m;i++)        {            scanf("%d%d",&a,&b);            add(a,b);        }        bool flag=1;        for(int i=1;i<=n;i++)        {            if(!dfn[i])            tarjan(i);        }        if(colcnt==1)puts("Yes");        else puts("No");    }    return 0;}

Kosaraju:

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <vector>#define maxn 10010using namespace std;vector<int> g[maxn];vector<int> ng[maxn];vector<int> s;int vis[maxn];int scc[maxn];int cnt;void dfs1(int x){    if(vis[x])return;    vis[x]=1;    for(int i=0;i<g[x].size();i++)    {        dfs1(g[x][i]);    }    s.push_back(x);}void dfs2(int x){    if(scc[x])return;    scc[x]=cnt;    for(int i=0;i<ng[x].size();i++)    {        dfs2(ng[x][i]);    }}int kosaraju(int n){    memset(vis,0,sizeof(vis));    memset(scc,0,sizeof(scc));    for(int i=1;i<=n;i++)    {        dfs1(i);    }    cnt=0;    for(int i=n-1;i>=0;i--)    {        if(!scc[s[i]])        {            cnt++;            dfs2(s[i]);            if(cnt>1)return 0;        }    }    return 1;}void init(int n){    for(int i=0;i<=n;i++)    {        g[i].clear();        ng[i].clear();    }        s.clear();}int main(){    int n,m;    int a;    while(scanf("%d%d",&n,&m)==2)    {        if(m==0&&n==0)break;        init(n);        int a,b;        for(int i=0;i<m;i++)        {            scanf("%d%d",&a,&b);            g[a].push_back(b);            ng[b].push_back(a);        }        if(kosaraju(n))puts("Yes");        else puts("No");    }    return 0;}

还是tarjan比较快