HDU 4857 逃生(拓扑排序 小的尽量在前)

xiaoxiao2021-02-28  91

糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。  现在有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<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int maxn = 1e5+5; vector<int> g[maxn]; int degree[maxn], ans[maxn], n, m; void topSort() { priority_queue<int, vector<int>, less<int> > pq; for(int i = 1; i <= n; i++) if(!degree[i]) pq.push(i); int flag = 0, p = 1; while(!pq.empty()) { int u = pq.top(); pq.pop(); ans[p++] = u; for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; degree[v]--; if(!degree[v]) pq.push(v); } } for(int i = p-1; i >= 1; i--) printf("%d%c", ans[i], i==1 ? '\n' : ' '); } int main(void) { int t; cin >> t; while(t--) { scanf("%d%d", &n, &m); memset(degree, 0, sizeof(degree)); for(int i = 1; i <= n; i++) g[i].clear(); while(m--) { int u, v; scanf("%d%d", &u, &v); g[v].push_back(u); degree[u]++; } topSort(); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-96274.html

最新回复(0)