HDU 4857 逃生(反向建边的拓扑排序+贪心思想)

逃生

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7736    Accepted Submission(s): 2248

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
 
Author
CLJ
 
Source
 
Recommend
We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 
 
分析:
n个元素,m组约束条件,猜测拓扑排序可以解决
约束条件a b表示a必须在b之前
题目给的要求是数字小的尽可能的排前面
根据贪心的思想,越前面的越重要,所以我们先将数字大的不重要的放后面,
这样一直往前放,最后放的才是数字小的(在满足约束的条件下,拓扑的作用就是要保证满足约束)
所以我们反向建边,每次选择数字较大的,从后面开始往前面放
这样一开始放的就是最不重要的位置(最后)
最后放的则是最前面的位置(第一个)
当然,这一切的放置都是在满足约束条件的前提下进行的
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
int mon1[]= {,,,,,,,,,,,,};
int mon2[]= {,,,,,,,,,,,,};
int dir[][]= {{,},{,-},{,},{-,}}; int getval()
{
int ret();
char c;
while((c=getchar())==' '||c=='\n'||c=='\r');
ret=c-'';
while((c=getchar())!=' '&&c!='\n'&&c!='\r')
ret=ret*+c-'';
return ret;
} #define max_v 30005
int indgree[max_v];
vector<int> vv[max_v];
priority_queue<int,vector<int>,less<int> > q;
int n,m;
int a[max_v];
void tpsort()
{
for(int i=; i<=n; i++)
{
if(indgree[i]==)
q.push(i);
}
int temp;
int cnt=;
int k=n;
while(!q.empty())
{
temp=q.top();
q.pop();
a[k--]=temp;
cnt++;
for(int i=; i<vv[temp].size(); i++)
{
indgree[vv[temp][i]]--;
if(indgree[vv[temp][i]]==)
q.push(vv[temp][i]);
}
}
}
int main()
{
int t;
int x,y;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m); memset(indgree,,sizeof(indgree));
for(int i=; i<=n; i++)
vv[i].clear();
while(!q.empty())
q.pop(); for(int i=; i<=m; i++)
{
scanf("%d %d",&y,&x); if(count(vv[x].begin(),vv[x].end(),y)==)
{
vv[x].push_back(y);
indgree[y]++;
} }
tpsort();
for(int i=; i<=n; i++)
{
if(i==)
printf("%d",a[i]);
else
printf(" %d",a[i]);
}
printf("\n");
}
return ;
}
/*
分析:
n个元素,m组约束条件,猜测拓扑排序可以解决 约束条件a b表示a必须在b之前 题目给的要求是数字小的尽可能的排前面 根据贪心的思想,越前面的越重要,所以我们先将数字大的不重要的放后面, 这样一直往前放,最后放的才是数字小的(在满足约束的条件下,拓扑的作用就是要保证满足约束) 所以我们反向建边,每次选择数字较大的,从后面开始往前面放 这样一开始放的就是最不重要的位置(最后) 最后放的则是最前面的位置(第一个) 当然,这一切的放置都是在满足约束条件的前提下进行的
*/
上一篇:BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心


下一篇:POJ3687 Labeling Balls(拓扑排序\贪心+Floyd)