HDU4856(逃生)

题目传送门
在这里插入图片描述

思路

题目意思很明朗,但是坑属实有点大,而且我到现在也没想清楚为什么是反向建图,反向建图为什么能够AC我没找到一个合理的解释。最开始就是直接正向建图通过优先队列的小根堆强行拓扑排序输出完事,交了很多发都是WA。实在想不到错误原因,好在看了一组测试数据才明白为啥会错误。

input:
1
3 1
3 1
answer:
3 1 2
错误答案
2 3 1

错误的理由很简单,题目要求有钱人先站在前面(编号小)。3站在1的前面之后,虽然没有其他约束条件但是有"隐含条件"的限制啊,2应该排在1的后面。也就是形成312的序列。如果采用小根堆维护实际上第一次访问队头元素就是2了,直接跨越了1 - 2的约束条件。但是为什么反向建图 + 大根堆 + 逆序输出能AC?其实大根堆就已经确保了序号大先输出,转成逆序输出就在后面了。但是给不了足够的证明过程,留一个小坑吧~

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
using namespace std;
const int maxn = 3e4+5;
const int maxm = 1e5+5;
struct edge{
	int to;
	int next;
}e[maxm];
vector<int>v;
priority_queue<int>q;			//默认大根堆
int head[maxn];
int s[maxn];
int cnt,n,m;
inline void clear_set()
{
	cnt = 0;
	memset(head,-1,sizeof(head));
	memset(s,0,sizeof(s));
	while(!q.empty())	q.pop();
	v.clear();
}
inline void addedge(int x,int y)
{
	e[cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt++;
}
inline void topsort()
{
	for(int i = 1;i <= n;i++){
		if(s[i] == 0){
			q.push(i);
		}
	}
	while(!q.empty()){
		int p = q.top();
		v.push_back(p);
		q.pop();
		for(int i = head[p];~i;i = e[i].next){
			if(--s[e[i].to] == 0){
				q.push(e[i].to);
			}
		}
	}
	for(int i = n-1;i > 0;i--){
		printf("%d ",v[i]);
	}
	printf("%d\n",v[0]);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--){
		clear_set();
		scanf("%d%d",&n,&m);
		while(m--){
			int x,y;
			scanf("%d%d",&x,&y);
			addedge(y,x);s[x]++;
		}
		topsort();
	}
	return 0;
}

愿你走出半生,归来仍是少年~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值