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;
}
posted @ 2012-03-23 15:44  Because Of You  Views(439)  Comments(0Edit  收藏  举报