poj 2762

来源:互联网 发布:mysql教程视频下载 编辑:程序博客网 时间:2024/06/05 18:56

http://poj.org/problem?id=2762
题意:给你n个房间,m条单向边,问你对于任意的x,y是否都有一条道路从x到y,或者从y到x。

思路:先用tarjan缩点,再用拓扑排序,如果发现去掉一个点之后有新增两个入度为0的点,则不能。

附上测试数据
4 4
1 2
2 3
3 4
2 4
Yes

4 3
1 2
2 3
2 4
No

#include <iostream>#include <stdio.h>#include <string.h>#include <vector>#include <queue>#include <algorithm>#define maxn 1005using namespace std;vector<int>edge[maxn];vector<int>Edge[maxn];int DFN[maxn],LOW[maxn],belong[maxn];int Stack[maxn];bool Instack[maxn];int Index,cnt,top;bool vis[maxn];int in[maxn];void Tarjan(int u){    int v;    DFN[u]=LOW[u]=++Index;    Stack[++top]=u;    Instack[u]=true;    for(int i=0;i<edge[u].size();i++)    {        v=edge[u][i];        if(DFN[v]==0)        {            Tarjan(v);            LOW[u]=min(LOW[v],LOW[u]);        }        else if(Instack[v])            LOW[u]=min(LOW[u],DFN[v]);    }    if(DFN[u]==LOW[u])    {        cnt++;        do        {            v=Stack[top--];            Instack[v]=false;            belong[v]=cnt;        }        while(u!=v);    }}bool topo(){    queue<int>q;    memset(vis,false,sizeof(vis));    int ans=0;    for(int i=1;i<=cnt;i++)    {        if(in[i]==0)        {            q.push(i);            ans++;        //    cout<<"i="<<i<<endl;        }    }    if(ans>1)return false;    while(!q.empty())    {        ans=0;        int cur=q.front();q.pop();        for(int i=0;i<Edge[cur].size();i++)        {            int v=Edge[cur][i];            in[v]--;            if(in[v]==0&&!vis[v])            {                ans++;                q.push(v);                vis[v]=true;            }        }        //cout<<cur<<" "<<ans<<endl;        if(ans>1)return false;    }    return true;}void init(int n){    Index=top=cnt=0;    memset(DFN,0,sizeof(DFN));    for(int i=1;i<=n;i++)    {        edge[i].clear();        Edge[i].clear();    }}int main(){    int t,n,m;    cin>>t;    while(t--)    {        cin>>n>>m;        init(n);        for(int i=0;i<m;i++)        {            int a,b;            scanf("%d%d",&a,&b);            edge[a].push_back(b);        }        for(int i=1;i<=n;i++)            if(DFN[i]==0)                Tarjan(i);        memset(in,0,sizeof(in));        for(int u=1;u<=n;u++)        {            for(int j=0;j<edge[u].size();j++)            {                int v=edge[u][j];                if(belong[u]!=belong[v])                {              //      cout<<"from"<<belong[u]<<" to"<<belong[v]<<endl;                    Edge[belong[u]].push_back(belong[v]);                    in[belong[v]]++;                }            }        }        topo()?puts("Yes"):puts("No");    }}