Codeforces Beta Round #89 (Div. 2)E题,给一联通的无向图,求确定每边的方向,使得任意两点可达

 
/*
题意:给一无向图,现在要确定每边的方向,使得任意两点可达,一定存在。
思想:用Tarjan算法求双连通分量,将深入的边与使low值变小的边存起来。其它还没确定的随便选个方向即可
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn=110000;
const int maxm=2100000;
struct edge
{
	int u,v,next;
	bool flag;
}e[maxm];
int n,m,edgeNum,top,top1,cnt,tnum,first[maxn],low[maxn],DFN[maxn],q[maxn],q1[maxm];
bool inq[maxn];
void Addedge(int u,int v)
{
	e[edgeNum].u=u,e[edgeNum].v=v,e[edgeNum].flag=false,e[edgeNum].next=first[u],first[u]=edgeNum++;
	e[edgeNum].u=v,e[edgeNum].v=u,e[edgeNum].flag=false,e[edgeNum].next=first[v],first[v]=edgeNum++;
}

void DFS(int t,int p,int e1)
{
	DFN[t]=low[t]=++tnum;
	q[top++]=t;
	q1[top1++]=e1;
	if(e1!=-1) e[e1].flag=true;
	inq[t]=true;

	int j,k;
	for(k=first[t];k!=-1;k=e[k].next)
	{
		j=e[k].v;
		if(j==p) continue;
		if(!DFN[j])
		{
			DFS(j,t,k);
			if(low[t]>low[j])
				low[t]=low[j];
		}
		else if(inq[j]&&low[t]>DFN[j])
		{
			q1[top1++]=k;//绕回去
			e[k].flag=true;
			low[t]=DFN[j];
		}
	}

	if(DFN[t]==low[t])
	{
		++cnt;
		do
		{
			inq[q[--top]]=false;
		}while(q[top]!=t);
	}
}

int main()
{
	int i,u,v;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(first,-1,sizeof(first));
		edgeNum=0;
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&u,&v);
			Addedge(u,v);
		}

		memset(low,0,sizeof(low));
		memset(DFN,0,sizeof(DFN));
		memset(inq,false,sizeof(inq));
		top1=top=cnt=tnum=0;
		for(i=1;i<=n;i++)
			if(!DFN[i])
				DFS(i,-1,-1);

		if(cnt!=1)
		{
			printf("0\n");
			continue;
		}
		//DFS1(1);
		for(i=0;i<edgeNum;i+=2)
			if(e[i].flag==false&&e[i+1].flag==false)
				q1[top1++]=i;//随便确定一个方向
	//	printf("%d\n",top1);
		for(i=1;i<top1;i++)
			printf("%d %d\n",e[q1[i]].u,e[q1[i]].v);
	}
	return 0;
}

你可能感兴趣的:(算法,struct)