codeforces 118E Bertown roads 边双连通

http://codeforces.com/problemset/problem/118/E

给定一幅连通的无向图,输入n、m以及m条边

要求给每条边一个方向,即把无向图转换成有向图,然后输出每条边(a b 表示a指向b)

要求转换后的图两两间依然可以互相到达。

如果不可能,输出0;

方法:如果原图中存在割边,输出0;

反之,随便从某个点开始dfs,把搜到的边一次输出来就好了

因为没有桥,则原图是一个双连通分量,两两间可以互相搜到

 

 

View Code
#include<cstdio>

#include<vector>

#include<set>

#include<cstring>

using namespace std;

const int maxn = 300010;

struct Edge{

    int s,t;

    int next;

    int vis;

}edge[2*maxn];

int head[maxn],E=0;

void add_edge(int s,int t)

{

    edge[E].s=s;

    edge[E].t=t;

    edge[E].vis=0;

    edge[E].next=head[s];

    head[s]=E++;

}

bool bridge;

int Time, dfn[maxn],low[maxn];

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

set<pair<int,int> >ans;

void dfs(int s)

{

    int i,t,id;

    dfn[s]=low[s]=++Time;

    for(i=head[s];i!=-1;i=edge[i].next)

    {

        if(edge[i].vis) continue;

        ans.insert(make_pair(s,edge[i].t));

        edge[i].vis=edge[i^1].vis=1;

        t=edge[i].t;

        if(!dfn[t])

        {

            dfs(t);

            low[s]=min(low[s],low[t]);

        }

        else low[s]=min(low[s],dfn[t]);

        if(low[t]>dfn[s]) 

        {

            bridge=true;

            return ;

        }

    }

}

void SCC(int n)

{

    int i;

    Time=0;

    memset(dfn,0,sizeof(int)*(n+1));

    for(i=1;i<=n;i++) if(!dfn[i])

        dfs(i);

}

int main()

{

    int n,m,i,j,a,b;

    scanf("%d%d",&n,&m);

    memset(head,-1,sizeof(head));

    for(i=1;i<=m;i++)

    {

        scanf("%d%d",&a,&b);

        add_edge(a,b);

        add_edge(b,a);

    }

    bridge=false;

    SCC(n);

    if(bridge) puts("0");

    else 

    {

        for(set<pair<int,int> >::iterator it=ans.begin();it!=ans.end();it++)

            printf("%d %d\n",*it);

    }

    return 0;

}

你可能感兴趣的:(codeforces)