- 这道题好像用差分约束也能解决
学了差分约束再来补一下
思路
- 这道题给定了多个相对关系,那么就要从关系上处理
思考后发现,有的员工是处于奖金最底层的,因为万恶的资本家要把奖金尽可能的压低,因此,一些员工在别人的评价中没有被列为比其他人高的话,那么这个员工就只能是奖金最底层。
而对于那些比这个员工高的,都要加一块钱(压价压到最低)
又因为可能会出现 a < b, b < c, a < c 的情况,这样如果不加以限制的话c可能就会比a多两块钱,但是按照题意的话是只会多一块钱的。
也就是说,如果他被给钱了在后续就不要更新了。
不合理方案情况
- 对于不合理的方案,其实就是建好图后判断是否出现了环,如果出现了环就表明无法进行拓扑排序,也就不合题意。
总结:
- 反向建边,小的指向大的
- 对那些第一次就更新的就标记上,防止后续再次更新,因为后续的出现只会让这个人的钱更多,而如果标记上就会把价格压到最低。
- 如果最后还有未标记的,就说明是孤立的,不合题意。
- 得到答案
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 10010, M = 20010;
int n, m;
typedef long long ll;
struct Edge{
int u, v, next;
}edge[N];
int head[N], tot, money[N], in[N];
bool vis[N];
void add(int u, int v){
edge[tot].u = u;
edge[tot].v = v;
edge[tot].next = head[u];
head[u] = tot ++;
}
void topsort(){
queue<int> q;
for(int i = 1; i <= n; i ++)
if(!in[i]){
q.push(i);
money[i] = 100;
//vis[i] = true;
}
while(q.size()){
int t = q.front();
q.pop();
vis[t] = true;
for(int i = head[t]; i != -1; i = edge[i].next){
int v = edge[i].v;
if(vis[v])
continue;
in[v] --;
money[v] = money[t] + 1;
if(!in[v])
q.push(v);
}
}
}
int main(){
cin >> n >> m;
memset(head, -1, sizeof head);
for(int i = 1; i <= m; i ++){
int u, v;
cin >> u >> v;
in[u] ++;
add(v, u);
}
topsort();
ll ans = 0;
bool flag = true;
for(int i = 1; i <= n; i ++)
if(!vis[i])
flag = false;
if(!flag)
cout << "Poor Xed" << endl;
else{
for(int i = 1; i <= n; i ++)
ans += money[i];
cout << ans << endl;
}
return 0;
}