D149 拓扑排序 U201733 奖金

D149 拓扑排序 U201733 奖金_哔哩哔哩_bilibili

 

U201733 奖金 - 洛谷

每位员工奖金最少为100元,部分员工之间的奖金数存在大于关系,如果存在合理方案,输出最少总奖金。

思路

点之间的大于关系可以用有向边表示,建图后,如果是有向无环图,则有解;如果是有向有环图,则无解

各点的到起点的距离初值均为 100,边权均为 1

跑拓扑排序,按最长路更新各点到起点的距离,对于从 $u$ 到 $v$ 的边,转移方程为 $d[v]=max(d[v],d[u]+1)$

最后,对各点的 d 值求和即答案

相关板子:

D01【模板】拓扑排序 - 董晓 - 博客园

 

// 拓扑排序 O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=10010;
int n,m,cnt;
vector<int> e[N];
int rd[N],d[N];

bool topo(){
  for(int i=1;i<=n;i++) d[i]=100; //各点初值
  queue<int> q;
  for(int i=1; i<=n; i++) if(!rd[i]) q.push(i);
  while(!q.empty()){
    int u=q.front(); q.pop();
    cnt++; //记录点数
    for(auto v:e[u]){
      d[v]=max(d[v],d[u]+1); //起点到v的最长路
      if(--rd[v]==0) q.push(v); //入度为0 则入队
    }
  }
  return cnt==n;
}
int main(){
  cin>>n>>m;
  for(int i=1,a,b; i<=m; i++){
    cin>>a>>b;
    e[b].push_back(a); //从b向a连边
    rd[a]++; //记录入度
  }
  if(topo()){ //如果拓扑排序成功
    int ans=0;
    for(int i=1; i<=n; i++) ans+=d[i];
    cout<<ans;
  }
  else puts("Poor Xed");
}
 

 

posted @ 2026-05-02 18:31  董晓  阅读(99)  评论(0)    收藏  举报