题意:发奖金,地位相同的人发的奖金一样,地位高的多发一点,怎样使得所发出的钱最少又能满足要求
思路:低的在前面,高的在后面,所以应用拓补排序,把相同层次入度为0的点都赋值为相同钱数,把这点存起来,然后把跟这些点有关系的点的入度减一
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
using namespace std;
const int M=10005;
struct node
{
int v;
int next;
} edge[2*M];
int head[M],vis[M],in[M],st,num,tmp[M];
int n,m;
void add(int u,int v)
{
edge[num].v=v;
edge[num].next=head[u];
head[u]=num++;
}
int topbu()
{
memset(vis,0,sizeof(vis));
int i,j=0,k,c=0,sum=0;
while(1)
{
k=0;
for(i=1; i<=n; i++)
{
if(!vis[i] && in[i]==0)
{
vis[i]=1;
c++;
sum+=(888+j);
tmp[k++]=i;
}
}
if(c>=n)return sum;
if(k==0)return -1;
for(i=0; i<k; i++)
{
int t=tmp[i];
for(int kk=head[t]; kk!=-1; kk=edge[kk].next)
{
int v=edge[kk].v;
in[v]--;
}
}
j++;
}
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
memset(in,0,sizeof(in));
memset(head,-1,sizeof(head));
num=0;
int a,b;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&a,&b);
in[a]++;
add(b,a);
}
printf("%d\n",topbu());
}
return 0;
}