题意:工人发工资,每个个人都有要求,比某人多,问满足搜有人要求的最小总工资数。
思路:逆拓扑排序
之前都是谁大谁是头节点,但是这题如果谁大谁为头的话,那么头结点的工资将不停的改变,有点麻烦,但是根节点工资永远不会变,所以可以反过来,谁小谁当根节点,也就是出度变入度,入度变出度,剩下和拓扑一样,只不过在求个和
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int num[10005];
int reward[10005];
vector<int> v[10005];
int c_sum = 0;
bool find(int a,int b)
{
int i;
for(i = 0; i < v[b].size(); i++)
{
if(v[b][i] == a)
return true;
}
return false;
}
void topsort(int n)
{
queue<int> q;
int i,sum = 0;
for(i = 1; i <= n; i++)
{
if(!num[i])
q.push(i);
}
while(!q.empty())
{
int t = q.front();c_sum--;q.pop();sum += reward[t];
for(i = 0; i < v[t].size(); i++)
{
num[v[t][i]]--;
reward[v[t][i]] = reward[t]+1;
if(!num[v[t][i]])
{
q.push(v[t][i]);
}
}
}
if(c_sum > 0 )
printf("-1\n");
else
printf("%d\n",sum);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m) != EOF)
{
int i,a,b;
c_sum = n;
for(i = 1;i <= n; i++)
{
v[i].clear();
reward[i] = 888;
num[i] = 0;
}
for(i = 0; i < m; i++)
{
scanf("%d%d",&a,&b);
if(!find(a,b))
{
v[b].push_back(a);
num[a]++;
}
}
topsort(n);
}
return 0;
}