题意:
给出一个无向图,将某些无向边改造为单向边,使图变为强连通
分析:
将割边保留,双联通分量中的边改为单向边即可。
/*
无向图转化为有向图
保证图的连通性
*/
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e3+10;
struct node{
int to;
int nxt;
int flag;
}edge[maxn*maxn];
int low[maxn],dfn[maxn];
int index;
int head[maxn],tot;
void addedge(int u,int v){
edge[tot].to=v;
edge[tot].nxt=head[u];
edge[tot].flag=-1;
head[u]=tot++;
}
void init(){
memset(head,-1,sizeof head);
memset(dfn,0,sizeof dfn);
index=tot=0;
}
void tarjan(int u,int pre){
int v;
low[u]=dfn[u]=++index;
for(int i=head[u];i!=-1;i=edge[i].nxt){
v=edge[i].to;
if(v==pre) continue;
if(edge[i].flag!=-1) continue; //注意这,如果是个双联通分量,不continue的话,会改变方向。
edge[i].flag=1;
edge[i^1].flag=0;
if(!dfn[v]){
tarjan(v,u);
if(low[u]>low[v]){
low[u]=low[v];
}
if(low[v]>dfn[u]){
edge[i].flag=1;
edge[i^1].flag=1;
}
}else if(low[u]>dfn[v]){
low[u]=dfn[v];
}
}
}
int main(){
int n,m;
int Case=1;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
init();
while(m--){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i,i);
}
}
printf("%d\n\n",Case++);
for(int i=0;i<tot;i++){
if(edge[i].flag==1){
printf("%d %d\n",edge[i^1].to,edge[i].to);
}
}
printf("#\n");
}
}