HDU 4857 逃生 【拓扑排序+反向建图+优先队列】
逃生
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6686 Accepted Submission(s): 1958
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
【题意】:有N个人,M个优先级a,b表示a优先于b,并且每个人有个编号的优先级,输出顺序。
拓扑排序,因为需要尽可能让编号较小的在前面,比如有如下约束
1->4->2 5->3->2
如果我们考虑正向建图的话得出的拓扑序列为 1 4 5 3 2
但是实际上,在图中 1 4 与 5 3 之间并没有约束,并且负责人在排序的时候会先去考虑 3 号的位置,于是有另一种结果 1 5 3 4 2 。
可见,第二种结果才是正确的,因为较小的编号总是优先选择靠前。
因为正向建图求拓扑序列的过程中,编号较小的点可能会被更大的点挡住,于是我们采用逆向建图的方法,然后用大顶堆维护,把编号较大的点先选出来,最后反转数组即可。
题意大抽象后概是这样的:给定一个有向图,将其按线性优先级输出。题目大致一扫,可以明白是个赤果果的拓扑排序。以前学过一点拓扑排序,后来给忘掉
了。拓扑排序就是解决对有向图的点进行线性排序的相关问题。假设给定一标记优先级的有向图,那么每个有向边通向的点的入度都要+1,这样的标记后,入度为
0的点就可以看成是优先级最高的点(因为没有点在它前面去连接它)。把此点取出,与这个点相连的其他点的边也就全部都要消掉了,同时将它们的入度减去1;
这样会产生新的入度为0的点,那么这个点就是剩下的点中的优先级最高的点,重复上述的更新过程即可。此题有坑,可能会有多个拓扑环;还有此题要求输出的点
如果没有拓扑关系则按照小编号在前的方式排列。看到这个条件第一反应是在取优先级高的点的过程中用优先队列去写,先出队列的就是编号较小的,这么想似乎没
错。但是后来debug了下,假如有一有向图关系是这样的:6->3->1;5->4->2;这样的话按照最小堆来进行拓扑排序会出这样的结果:5 4 2 6 3 1;但是实际上
我们可以把6 3 1 这个拓扑环放在前面,生成6 3 1 5 4 2这样的线性序列。究其原因,我们优先队列先弹出的是编号较小的符合条件的点,但实际上这个点只能算
是该拓扑环排序后的头结点,我们想要保证让小号的全部尽可能地放在前面,我们需要保证拓扑环的尾部的小号也在前面。这样来想一下可以发现先出编号小的是
不完善的。于是我们可以考虑逆向思维,先弹出序号大的,那么这样先出队列的就是编号最大的;但是我们有需要编号最大的在最后输出,换句话说就是编号最大的
是作为优先级最低的;那么我们把有向图也给逆向储存,这样按优先级条件弹出的顺序才会一致(优先弹出优先级最低的)。大致思路明白后代码实现就很简单了。
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,n,x) for(int i=(x); i<(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e18;
const int maxn = 1e5 + 20;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int n,m,num,ok,u,v;
/*
4—>2
5—>1—>3
正常情况下字典序最小的拓扑序应该是:4 2 5 1 3
这种规则下,则应该是: 5 1 4 2 3
*/
vector<int> G[maxn];
int ans[maxn];
char s[10];
int inDeg[maxn],x;
void topSort()
{
priority_queue<int> q; //优先队列默认的是数据大的优先级高
int num=0;
while(!q.empty()) q.pop();
for(int i=1;i<=n;i++) if(!inDeg[i]) q.push(i);
while(!q.empty())
{
int now = q.top();
q.pop();
ans[++num]=now;
for(int i=0; i<G[now].size(); i++)
{
int nxt = G[now][i];
if(--inDeg[nxt] == 0) q.push(nxt);
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ms(inDeg,0);
ms(ans,0);
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
G[v].push_back(u);
inDeg[u]++;
}
topSort();
for(int i=n;i>=1;i--)
{
if(i!=1) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
}
return 0;
}
/*
1
5 10
3 5
1 4
2 5
1 2
3 4
1 4
2 3
1 5
3 5
1 2
*/
HDU 4857 逃生 【拓扑排序+反向建图+优先队列】的更多相关文章
- hdu 4857 逃生 拓扑排序+逆向建图
逃生 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Descr ...
- HDU 2647 Reward 【拓扑排序反向建图+队列】
题目 Reward Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to d ...
- hdu 4857 逃生 拓扑排序+PQ,剥层分析
pid=4857">hdu4857 逃生 题目是求拓扑排序,但不是依照字典序最小输出,而是要使较小的数排在最前面. 一開始的错误思路:给每一个点确定一个优先级(该点所能到达的最小的点) ...
- HDU2647(拓扑排序+反向建图)
题意不说了,说下思路. 给出的关系是a要求的工资要比b的工资多,因为尽可能的让老板少付钱,那么a的工资就是b的工资+1.能够确定关系为a>b,依据拓扑排序建边的原则是把"小于" ...
- hdoj--4857--逃生(拓扑排序+反向建图)
逃生 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...
- hdu 4857 逆向拓扑排序+反向输出
/*一组测试实例 4 4 2 3 1 2 4 */ #include<stdio.h> #include<string.h> #include<queue> usi ...
- Educational Codeforces Round 25 E. Minimal Labels 拓扑排序+逆向建图
E. Minimal Labels time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- 逃生 HDU 4857(反向建图 + 拓扑排序)
逃生 链接 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必 ...
- HDU4857——逃生(反向建图+拓扑排序)(BestCoder Round #1)
逃生 Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社会 ...
随机推荐
- 【bzoj2049】[Sdoi2008]Cave 洞穴勘测 LCT
题目描述 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如 ...
- text-overflow使用文字超多div的宽度或超过在table中<td>
关键字:text-overflow:ellipsis 语法:text-overflow:clip | ellipsis 取值 clip:默认值.不显示省略标记(...),而是简单的裁切. ellips ...
- 2017 Multi-University Training Contest - Team 2 Puzzle
题目大意: 给定n, m, p.然后按照一个规则往n*m的方格里填数,最后一个方格是空格,然后玩拼图游戏,问能否复原 规则是:把1~n*m-1的排列中的第1,p+1,2*p+1.....个数依次取出来 ...
- ARC076 F Exhausted? Hall定理 + 线段树扫描线
---题面--- 题目大意: 有n个人,m个座位,每个人可以匹配的座位是[1, li] || [ri, m],可能有人不需要匹配座位(默认满足),问最少有多少人不能被满足. 题解: 首先可以看出这是一 ...
- HDU3038:How Many Answers Are Wrong(带权并查集)
How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- 两个数组的交集 II [ LeetCode - 350 ]
原题地址:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/description/ 给定两个数组,写一个方法来计算 ...
- Every Programmer Should Know These Latency Numbers
Every Programmer Should Know These Latency Numbers 1秒=1000毫秒(ms) 1秒=1,000,000 微秒(μs) 1秒=1,000,000,00 ...
- 使用命令wsimport生成WebService客户端
使用命令wsimport生成WebService客户端 wsimpost命令有几个重要的参数: -keep:是否生成java源文件 -d:指定输出目录 -s:指定源代码输出目录 -p ...
- Spring学习--通过注解配置 Bean (三)
组件装配: <context:component-sacan> 元素还会自动注册 AutowiredAnnotationBeanPostProcesser 实例 , 该实例可以自动装配具有 ...
- 五分钟搞懂Vuex
这段时间一直在用vue写项目,vuex在项目中也会依葫芦画瓢使用,但是总有一种朦朦胧胧的感觉.于是决定彻底搞懂它. 看了一下午的官方文档,以及资料,才发现vuex so easy! 作为一个圈子中的人 ...