逃生

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

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
 
这题用优先队列死活找不到原因,然后看了详细题解,总算是弄懂那里错了。好题目!
例子:
6 -> 3 -> 1
5 -> 4 -> 2
直接拓扑排序的结果是:5 4 2 6 3 1 ,结果是错误的,因为我们可以把1号安排到更前面的位置 即:6 3 1 5 4 2(正确答案)。
分析:对于多条弧或者边,我们是先删除弧尾结点比较小的结点即(5号结点比6号结点小,先删除以该点为尾的弧),而这也正是问题所在,我们希望的是优先删除弧头比较小的弧的(1号结点比2号结点小,因优先删除以1号为头的弧)。
所以正确做法是将边反过来,那么弧头就变成弧尾了!然后再用优先队列,输出的时候反过来就行了!附上错误代码和AC代码:
AC:
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
#include <functional>
#include <string.h>
using namespace std;
priority_queue<int>q;
const int N = ;
const int M = ;
int p[N];
int indegree[M];
struct Edge{
int v,next;
}edge[N];
int head[M];
void addEdge(int u,int v,int &k){
edge[k].v = v,edge[k].next = head[u],head[u]=k++;
}
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
head[i] = -;
indegree[i] = ;
}
int tot = ;
for(int i=;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
addEdge(b,a,tot); ///重点,反向弧
indegree[a]++;
}
for(int i=;i<=n;i++){
if(indegree[i]==){
q.push(i);
}
}
int k = ;
int id = ;
while(!q.empty()){
int u = q.top();
p[id++] = u;
q.pop();
for(int k = head[u];k!=-;k=edge[k].next){
if(indegree[edge[k].v]>) indegree[edge[k].v]--;
if(indegree[edge[k].v]==) q.push(edge[k].v);
}
}
for(int i=id-;i>;i--){
printf("%d ",p[i]);
}
printf("%d\n",p[]);
}
}

错误代码:

#include <stdio.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
#include <functional>
#include <string.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
const int N = ;
const int M = ;
int p[N];
int indegree[M];
struct Edge
{
int v,next;
} edge[N];
int head[M];
void addEdge(int u,int v,int &k)
{
edge[k].v = v,edge[k].next = head[u],head[u]=k++;
}
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
{
head[i] = -;
indegree[i] = ;
}
int tot = ;
for(int i=; i<m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
addEdge(a,b,tot);
indegree[b]++;
}
for(int i=; i<=n; i++)
{
if(indegree[i]==)
{
q.push(i);
}
}
int k = ;
int id = ;
while(!q.empty())
{
int u = q.top();
q.pop();
p[id++] = u;
for(int k = head[u]; k!=-; k=edge[k].next)
{
if(indegree[edge[k].v]>) indegree[edge[k].v]--;
if(indegree[edge[k].v]==) q.push(edge[k].v);
}
}
for(int i=; i<id-; i++)
{
printf("%d ",p[i]);
}
printf("%d\n",p[id-]);
}
}

hdu 4857(好题,反向拓扑排序)的更多相关文章

  1. HDU 4857 逃生 (反向拓扑排序 & 容器实现)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  2. HDU 4857 逃生(反向拓扑排序+优先队列)

    ( ̄▽ ̄)" //这题对序号输出有要求,较小的序号优先输出,所以用到优先队列 //优先队列是优先弹出值最大的,所以最后要反向输出结果,才是正确的output #include<iost ...

  3. HDU 4857 逃生(反向拓扑排序)

    传送门 Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社 ...

  4. hdu 4857 逆向建图+拓扑排序 ***

    题意:糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行.现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社会是不平等的,这些人有的穷有 ...

  5. HDU 2647 Reward【反向拓扑排序】

    Reward Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  6. 逃生(HDU4857 + 反向拓扑排序)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 题面是中文题面,就不解释题意了,自己点击链接去看下啦~这题排序有两个条件,一个是按给定的那个序列 ...

  7. CF-825E Minimal Labels 反向拓扑排序

    http://codeforces.com/contest/825/problem/E 一道裸的拓扑排序题.为什么需要反向拓扑排序呢?因为一条大下标指向小下标的边可能会导致小下标更晚分配到号码,导致字 ...

  8. HDU.3342 Legal or Not (拓扑排序 TopSort)

    HDU.3342 Legal or Not (拓扑排序 TopSort) 题意分析 裸的拓扑排序 根据是否成环来判断是否合法 详解请移步 算法学习 拓扑排序(TopSort) 代码总览 #includ ...

  9. HDU.1285 确定比赛名次 (拓扑排序 TopSort)

    HDU.1285 确定比赛名次 (拓扑排序 TopSort) 题意分析 裸的拓扑排序 详解请移步 算法学习 拓扑排序(TopSort) 只不过这道的额外要求是,输出字典序最小的那组解.那么解决方案就是 ...

随机推荐

  1. 数学算法:CF534A-Exam(思维)

    Exam time limit per test 1 second memory limit per test 256 megabytes input standard input output st ...

  2. n个人排队都不站在原来的位置

    一.题目描述 有n个人首先站成一排,请问,当n个人第二次再重新排列,每个人都不在原来的位置上,问有多少种站法.例如,原来有3个人,ABC,那么第二次每个人都不在原来的位置上有2种站法,BCA和CAB, ...

  3. hdu 1257最少拦截系统

    最少拦截系统 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的 ...

  4. 【Kubernetes】资源列表

    1.Kubernetes资源列表 https://www.cnblogs.com/linuxk/p/10436260.html

  5. luogu4169 [Violet]天使玩偶/SJY摆棋子 / bzoj2648 SJY摆棋子 k-d tree

    k-d tree + 重构的思想,就能卡过luogu和bzoj啦orz #include <algorithm> #include <iostream> #include &l ...

  6. 免费生成https证书以及配置

    http升级到https需要在nginx的配置中加入证书信息,查询资料后确定生成证书两种方案   第一种:自签名证书,然后开启 CloudFlare 的 CDN 服务   //确定是否安装openss ...

  7. IOS开发---菜鸟学习之路--(十九)-利用NSUserDefaults存储数据

    利用NSUserDefaults的可以快速的进行本地数据存储,但是支持的格式有限, 至于支持什么格式大家可以再自行脑补 我这边直接讲如何使用 NSUserDefaults 分为两部分 一个是存数据 N ...

  8. IOS笔记049-UITabBarController

    1.简单实现 效果:在视图底部显示一个工具栏 代码实现 // 创建窗口 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScre ...

  9. C++编程规范(101条准则)

    记录学习,方便以后查看.  2014-12-28 看完这本书,但是我做到的又有多少呢?确实有一部分 0 不要拘泥于小节 1 在高警告级别干净利落的进行编译,不放过任何警告 2 使用自动构建系统 3 使 ...

  10. Google Chrome开发者工具-移动仿真:触摸事件仿真

    如果你在开发PAD/手机所用WEB版应用,需要在桌面审查页面元素.调试脚本,模拟移动设备尺寸.事件.位置等信息, 那么可以使用Chrome开发者工具(DevTools)提供的强大的移动仿真功能,支持主 ...