题意大概是说把一个无向图转化为有向图,需要取出一些边,(双向变成单向),得到一个有向强连通图,显然,桥不能修改,加个标记就行了。代码如下:
/****************************
* author:crazy_石头
* date:2014/01/18
* algorithm:tarjan
* Pro:亲友团训练-图论1-B
***************************/
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <string>
using namespace std;
#define INF 1<<29
#define eps 1e-8
#define A system("pause")
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
const int maxn=200020;
const int maxm=20;
struct edge
{
int from,to,next;
int iscut;
}e[maxn<<1];
int head[maxn],dfn[maxn],low[maxn],instack[maxn],cnt,index,n,m;
inline void addedge(int u,int v)
{
e[cnt].from=u;
e[cnt].to=v;
e[cnt].next=head[u];
e[cnt].iscut=-1;
head[u]=cnt++;
}
inline void tarjan(int u,int f)
{
low[u]=dfn[u]=++index;
instack[u]=true;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v==f) continue;
if(e[i].iscut!=-1)continue;//不为-1说明该边已经修改过了;
e[i].iscut=1;//修改正向边,去掉反向边;
e[i^1].iscut=0;
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])//是桥的条件,则正反向边均可通过,桥是不能修改的;
{
e[i].iscut=1;
e[i^1].iscut=1;
}
}
else if(instack[v])
low[u]=min(low[u],dfn[v]);
}
}
inline void init()
{
ms(head,-1),cnt=0;
}
inline void gao()
{
index=0;
ms(low,0),ms(dfn,0),ms(instack,0);
rep(i,1,n)
if(!dfn[i]) tarjan(i,-1);
}
inline void solve()
{
rep(i,0,cnt-1)
if(e[i].iscut==1)printf("%d %d\n",e[i].from,e[i].to);
}
int main()
{
int test=1;
while(~scanf("%d%d",&n,&m),n||m)
{
init();
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
gao();
printf("%d\n\n",test++);
solve();
printf("#\n");
}
return 0;
}