【题解】【拓扑排序】混合图

混合图

Special Judge

Time Limit: 1000 ms   Memory Limit:128 MB

Description

Hzwer神犇最近又征服了一个国家,然后接下来却也遇见了一个难题。

Hzwer的国家有n个点,m条边,而作为国王,他十分喜欢游览自己的国家。他一般会从任意一个点出发,随便找边走,沿途欣赏路上的美景。但是我们的Hzwer是一个奇怪的人,他不喜欢走到自己以前走过的地方,他的国家本来有p1条有向边,p2条无向边,由于国王奇怪的爱好,他觉得整改所有无向边,使得他们变成有向边,要求整改完以后保证他的国家不可能出现从某个地点出发顺着路走一圈又回来的情况。(注:m=p1+p2.)

概述:给你一张混合图,要求你为无向图定向,使得图上没有环。

Input

第一行3个整数 n,p1,p2,分别表示点数,有向边的数量,无向边的数量。

第二行起输入p1行,每行2个整数 a,b 表示a到b有一条有向边。

接下来输入p2行,每行2个整数 a,b 表示a和b中间有一条无向边。

Output

对于每条无向边,我们要求按输入顺序输出你定向的结果,也就是如果你输出a b,那表示你将a和b中间的无向边定向为a->b。

注意,也许存在很多可行的解。你只要输出其中任意一个就好。

Sample Input

4 2 3
1 2
4 3
1 3
4 2
3 2

Sample Output

1 3
4 2
2 3

HINT

对于20%的数据 n<=10 p1<=10 p2<=5

对于30%的数据 n<=10 p1<=30 p2<=20

对于100%的数据 n<=100000 p1<=100000 p2<=100000

数据保证至少有一种可行解。


题解:

将图先拓扑排序,然后对于每一条无向边,选择在拓扑排序中出现顺序前的那个节点作为这条无向边的起点。


代码:

#include 
#include 
#include 
#include 
using std::stack;
using std::priority_queue;

const int maxn=100001;
int rudu[maxn],first[maxn],next[maxn],to[maxn],edgecount=1,_time,ans[maxn];

void addedge(int x,int y)
{
	next[edgecount]=first[x];
	first[x]=edgecount;
	to[edgecount]=y;
	++rudu[y];
	++edgecount;
}

stack sorting;

int main()
{
	int n,p1,p2,a,b;
	scanf("%d%d%d",&n,&p1,&p2);
	for(int i=1;i<=p1;++i)
	{
		scanf("%d%d",&a,&b);
		addedge(a,b);
	}
	for(int i=1;i<=n;++i)
	{
		if(!rudu[i])
		{
			sorting.push(i);
			ans[i]=++_time;
		}
	}
	do
	{
		int now=sorting.top();
		sorting.pop();
		for(int i=first[now];i!=0;i=next[i])
		{
			if(!(--rudu[to[i]]))
			{
				sorting.push(to[i]);
				ans[to[i]]=++_time;
			}
		}
	}
	while(!sorting.empty());
	for(int i=1;i<=p2;++i)
	{
		scanf("%d%d",&a,&b);
		if(ans[a]


你可能感兴趣的:(题解,C++,图论,拓扑排序,C++,图论,拓扑排序,题解)