现在的位置: 首页 > 综合 > 正文

HDU 4857 逃生 【拓扑排序+反向建图+优先队列】

2018年01月21日 ⁄ 综合 ⁄ 共 1433字 ⁄ 字号 评论关闭
文章目录

逃生

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 5   Accepted Submission(s) : 1

Font: Times New Roman | Verdana | Georgia

Font Size:

Problem Description

糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。

现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。

负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。

那么你就要安排大家的顺序。我们保证一定有解。

Input

第一行一个整数T(1 <= T <= 5),表示测试数据的个数。
然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。

然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。

Output

对每个测试数据,输出一行排队的顺序,用空格隔开。

Sample Input

1
5 10
3 5
1 4
2 5
1 2
3 4
1 4
2 3
1 5
3 5
1 2

Sample Output

1 2 3 4 5

/*
 题解:反向建图+优先队列
反向建图后,用最大值优先的优先队列来拓扑排序,这样能保证在可能的情况下,先选最大的,把最小的留到最后选
*/

#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
#define maxn 30002
int n,m,iq,in[maxn],ans[maxn];
using namespace std;

struct cmp{
	bool operator()(int &a,int &b)
	{
	return a<b;//大者优先
	}
};

vector <int> e[maxn];

void topo()
{
	priority_queue<int,vector<int>,cmp> q;//优先队列,大的在前面
	for(int i=1; i<=n; i++)
	{
		if(in[i]==0) q.push(i);
	}
	while(!q.empty())
	{
		int x=q.top();
		q.pop();
		ans[iq++]=x;//ans为逆向的拓扑排序
		for(int i=0; i<e[x].size(); i++)
		{
			in[e[x][i]]--;
			if(in[e[x][i]]==0) q.push(e[x][i]);
		}
	}
}

int main()
{
	int T,a,b;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d %d",&n,&m);
		for(int i=0; i<=n; i++) e[i].clear();//初始化
		while(m--)
		{
			scanf("%d %d",&a,&b);
			e[b].push_back(a);//运用栈,反向建图
			in[a]++;
		}
		iq=1;
		topo();
		printf("%d",ans[iq-1]);
		for(i=iq-2; i>=1; i--) printf(" %d",ans[i]);
		printf("\n");
	}
	return 0;
}

 

 

 

 

抱歉!评论已关闭.