题意:发奖金,最低是888,有n个人,m条边(u,v)。u的奖金必须大于v。问最少发多少奖金。
解:我们建反向边(V,U),即(V比U的奖金少),记录入度。从入度为0的点开始top排序就行了。按照bfs的写法,每次top到下一层,只需要在这层的基础上奖金+1就行了。输出-1的情况,显然是中间出现了环,我们只需要记录,度能为0的个数。为n就输出解,否则为-1.
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <string.h>
#include <map>
#include <set>
using namespace std;
#define MAXN 10005
#define LL long long
int du[MAXN],vis[MAXN],ans[MAXN];
int maze[MAXN][MAXN];
vector<int>g[MAXN];
struct node
{
int num,id;
node(int num,int id):num(num),id(id){}
};
int main()
{
int n,m,i,ans=0,tot;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<=n;i++)
{
g[i].clear();
du[i]=0;
vis[i]=0;
}
for(i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[v].push_back(u);
du[u]++;
}
queue<node>q;
ans=0;
tot=0;
for(i=1;i<=n;i++)
{
if(du[i]==0)
{
vis[i]=1;
q.push(node(888,i));
}
}
while(!q.empty())
{
node tx=q.front();
ans+=tx.num;
q.pop();
tot++;
int sz=g[tx.id].size();
for(i=0;i<sz;i++)
{
du[g[tx.id][i]]--;
if(!vis[g[tx.id][i]])
{
if(du[g[tx.id][i]]==0)
{
vis[g[tx.id][i]]=1;
q.push(node(tx.num+1,g[tx.id][i]));
}
}
}
}
if(tot==n)printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}