http://acm.hdu.edu.cn/showproblem.php?pid=2647
题意:n个人m个关系,其中a,b代表a应得的工资比b多,每人最少给888,还要求必须让所有人服气,求老板最少给多少工资。
思路:分层次的拓扑排序,每个层次的人工资相等。我们知道,如果按照能力高(这里代表应得工资多)的人在上,能力低的人在下建树的话,那么最底层的人工资最低为888,上面节点都是由这一节点累加过来的。要想实现这一效果,我们必须反向建树,原先统计入度的个数变为出度。这里用容器存储边,层次概念相对直观一点。
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 10005;
const int INF = 0x3f3f3f3f;
int deg[N], mon[N], n;
vector<int>edge[N];
int toposort()
{
queue<int>que;
int k = 0, sum = 0;
for(int i = 1; i <= n; i++)
{
if(deg[i] == 0)
{
que.push(i);
k++;
deg[i]--;
sum+=mon[i];
}
}
while(!que.empty())
{
int s = que.front();
que.pop();
for(int i = 0; i < edge[s].size(); i++)
{
int j = edge[s][i];
deg[j]--;
if(mon[s]+1>mon[j]) mon[j] = mon[s]+1;
if(deg[j] == 0)
{
que.push(j);
k++;
sum+=mon[j];
}
}
}
if(k == n) return sum;
else return 0;
}
int main()
{
// freopen("in.txt", "r", stdin);
int m, u, v;
while(~scanf("%d%d", &n, &m))
{
memset(deg, 0, sizeof(deg));
for(int i = 1; i <= n; i++)
{
mon[i] = 888;
edge[i].clear();
}
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &u, &v);
edge[v].push_back(u);
deg[u]++;
}
int ans = toposort();
if(ans) printf("%d\n", ans);
else printf("-1\n");
}
return 0;
}