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; }