问题是这样的, n个人, m个二元组, 对于每个二元组(a, b), 表示a的钱应该比b多.
每个人最少应该有100元, 求最后的总分配钱数.
/*
有两种思路, 一种是正常建边, 最后从在从拓扑序列的前面开始更新wage
第二种是反向建边, 在拓扑排序的时候就直接更新wage
第一种的常数大点.
主要的点是: 对于A->B, B->C, A->C这种关系, A应该最后保留有A->B边更新的信息.
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 1e4 + 600;
const int MAXM = 2e4 + 600;
int wage[MAXN], faz[MAXN];
int n, m;
int Xflag;
struct Edge{
int to, next;
} edges[MAXM];
int ihead[MAXN], ecnt;
int indegree[MAXN];
int deep[MAXN];
void init(){
memset(ihead, 0, sizeof(ihead));
memset(indegree, 0, sizeof(indegree));
// memset(deep, -1, sizeof(deep));
ecnt = 0;
}
void insert(int u, int v){
edges[++ecnt].to = v;
edges[ecnt].next = ihead[u];
ihead[u] = ecnt;
}
int checkChild(int u){// 返回u的wage
if(ihead[u] == 0){
return wage[u] = 100;
}
int rst = -0x3f3f3f3f, v;
for(int i = ihead[u]; i; i = edges[i].next){
v = edges[i].to;
rst = max(rst, wage[v]);
}
return wage[u] = rst + 1;
}
void topoSort(){
int cnt = 0;
queue<int> q;
for(int i = 0; i < n;){
if(indegree[++i] == 0){
q.push(i);
// deep[i] = 0;
++cnt;
}
}
int u, v;
stack<int> s;
while(q.size()){
u = q.front();
q.pop();
s.push(u);
for(int i = ihead[u]; i; i = edges[i].next){
v = edges[i].to;
faz[v] = u;
// --indegree[v];
if(--indegree[v] == 0){
q.push(v);
++cnt;
}
}
}
if(cnt != n){
Xflag = 1;
return;
}
while(s.size()){
u = s.top();
s.pop();
wage[u] = checkChild(u);
}
}
void topoSort(){
queue<int> q;
int cnt = 0;
for(int i = 0; i < n;){
if(indegree[++i] == 0){
q.push(i);
++cnt;
wage[i] = 100;
}
}
int u, v;
while(q.size()){
u = q.front();
q.pop();
for(int i = ihead[u]; i; i = edges[i].next){
v = edges[i].to;
wage[v] = max(wage[v], wage[u] + 1);
if(--indegree[v] == 0){
++cnt;
q.push(v);
}
}
}
if(cnt != n){
Xflag = 1;
return;
}
}
int main(){
init();
scanf("%d%d", &n, &m);
int u, v;
for(int i = 0; i < m; ++i){
scanf("%d%d", &u, &v);
// insert(v, u);// insert(u, v)
// ++indegree[u];// ++indegree[v]// 两个拓扑排序对应这里两个
}
topoSort();
int rst = 0;
for(int i = 0; i < n;){
rst += wage[++i];
}
if(Xflag){
printf("Unhappy!\n");
}
else{
printf("%d\n", rst);
}
return 0;
}