拓扑排序基础题——排序

题目

由于公司在2013年的销售业务成绩优秀,公司总经理心情大好,决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。于是总经理下令召开 m 方会谈。每位参加会谈的代表提出了自己的意见:“我认为员工 a 的奖金应该比 b 高!”。总经理决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元。
输入格式
第一行两个整数 n 和 m,表示员工总数和代表数;
接下来有 m 行,每行 2 个整数 a 和 b,表示某个代表认为第 a 号员工奖金应该比第 b 号员工高。
输出格式
若无法找到合理方案,则输出“Poor Xed”;否则输出一个数表示最少总奖金。
样例数据 1
输入
2 1
1 2
输出
201
备注
【数据规模】
80%的数据满足:n<=1000,m<=2000;
100%的数据满足:n<=10000,m<=20000。

很简单的一道拓扑排序

如果A的工资要比B高,那就从B向A连一条边

然后从入度为0的点开始统计

然后用ff来记录每个点的工资,当从点i指向点j的时候f[j]=max(f[j],f[i]+1)f[j]=max(f[j],f[i]+1)

最后的答案就是f[i],1&lt;=i&lt;=n∑f[i],1&lt;=i&lt;=n

因为直接双层循环要超时,所以只能循环队列来做,但如果m,n到了151^5的时候,就只能用特殊的数据结构来维护入度了

若一次循环中没有入度为0的点了,而还有点未处理,则有环,无解

代码

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    char ch=getchar();
    int res=0;
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
int adj[20005],nxt[20005],to[20005],dep[10005],in[10005],f[10005],n,m,cnt;
inline int sum(){
    int ans=0;
    for(int i=1;i<=n;i++)
    ans+=f[i];
    return ans;
}
inline void addedge(int u,int v)
{
    nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,in[v]++;
}
inline void _(int k)
{
    for(int e=adj[k];e;e=nxt[e])
    {
        in[to[e]]--;
        f[to[e]]=max(f[to[e]],f[k]+1);
    }
}
inline bool solve(){
    int tot=0;
    while(tot<n)
    {
        int t=0;
        for(int i=1;i<=n;i++)
        {
            if(in[i]==0)
            {
                t++,tot++;
                in[i]=1<<30;
                _(i);
            }
        }
        if(!t)
        {
            return false;
        }
    }
    return true;
}
int main(){
    n=read(),m=read();
    int a,b;
    for(int i=1;i<=n;i++)
    f[i]=100;
    for(int i=1;i<=m;i++)
    {
        a=read(),b=read();
        addedge(b,a);
    }
    if(solve()) cout<<sum()<<endl;
    else cout<<"Poor Xed"<<'
';
    return 0;
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366500.html