6082: 逃生 逆拓扑排序+优先队列

描述

 

糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。

现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。

负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。

那么你就要安排大家的顺序。我们保证一定有解。

 

输入

 

第一行一个整数T(1 <= T <= 5),表示测试数据的个数。
然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。

然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。

 

输出

 

对每个测试数据,输出一行排队的顺序,用空格隔开。

 

样例输入

 

1
5 10
3 5
1 4
2 5
1 2
3 4
1 4
2 3
1 5
3 5
1 2

样例输出

 1 2 3 4 5
 
采用逆向拓扑排序从后往前推,并用优先队列优先选取较小的点
复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e4+10,inf = 0x3f3f3f3f;
int gcd(int a,int b){return a==0?b:gcd(b%a,a);}
int n,m,t;
vector<int>g[N];
int cd[N];
void topsort()
{
    priority_queue<int> q;
    stack<int>s;
    for(int i=1;i<=n;i++)
        if(cd[i]==0)q.push(i),cd[i] = -1;
    while(!q.empty())
    {
        int x = q.top();q.pop();s.push(x);
        for(int i=0;i<g[x].size();i++)
        {
            cd[g[x][i]]--;
            if(cd[g[x][i]]==0)q.push(g[x][i]);
        }
    }
    cout<<s.top();s.pop();
    while(!s.empty())
    {
        cout<<" "<<s.top();s.pop();
    }
    cout<<endl;
}
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        memset(cd,0,sizeof(cd));
        for(int i=1;i<=n;i++)g[i].clear();
        for(int i=1;i<=m;i++)
        {
            int x,y; cin>>x>>y;
            g[y].push_back(x);
            cd[x]++;
        }
        topsort();
    }
     return 0;
}
复制代码

 

posted @   CRt0729  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示