Description
Input
Output
Sample Input
7 10 1 2 1 3 2 4 3 4 4 5 4 6 5 7 6 7 2 5 3 6 7 9 1 2 1 3 1 4 2 4 3 4 4 5 5 6 5 7 7 6 0 0
Sample Output
1 1 2 2 4 3 1 3 6 4 3 5 2 5 4 6 4 6 7 7 5 # 2 1 2 2 4 3 1 4 1 4 3 4 5 5 4 5 6 6 7 7 5 #
题意:已知一堆双向边,要求把尽可能多的双向边改成单向边,但任意两点仍然可以互相到达。
解题思路:除割边需要双向,其他的边按dfs顺序即可。
代码:
/* ***********************************************
Author :xianxingwuguan
Created Time :2014/1/18 18:59:49
File Name :F.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int maxn=2222;
int head[maxn],tol,low[maxn],dfn[maxn],Stack[maxn],indexx,top,n;
int mp[maxn][maxn];
int vis[maxn];
struct node
{
int next,to,cut,xiang;
}edge[300000];
void add(int u,int v)
{
edge[tol].to=v;
edge[tol].cut=-1;
edge[tol].next=head[u];
head[u]=tol++;
}
void tarjin(int u,int pre)
{
low[u]=dfn[u]=++indexx;
Stack[top++]=u;
int v;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre)continue;
if(edge[i].cut!=-1)continue;
edge[i].cut=1;
edge[i^1].cut=0;
if(!dfn[v])
{
tarjin(v,u);
if(low[u]>low[v])
low[u]=low[v];
if(low[v]>dfn[u])
{
edge[i].cut=1;
edge[i^1].cut=1;
}
}
else if(low[u]>dfn[v])
low[u]=dfn[v];
}
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int i,j,k,m;
int ncase=0;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
memset(head,-1,sizeof(head));
tol=0;
while(m--)
{
scanf("%d%d",&i,&j);
add(i,j);
add(j,i);
}
printf("%d\n\n",++ncase);
memset(dfn,0,sizeof(dfn));
indexx=top=0;
for(i=1;i<=n;i++)
if(!dfn[i])tarjin(i,i);
for(i=0;i<tol;i++)if(edge[i].cut==1)printf("%d %d\n",edge[i^1].to,edge[i].to);
puts("#");
}
return 0;
}
原文:http://blog.csdn.net/xianxingwuguan1/article/details/18458939