奖 金 奖金 奖金
题目
由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。
于是Mr.Z下令召开m方会谈。每位参加会谈的代表提出了自己的意见:“我认为员工a的奖金应该比b高!”Mr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元。
输入
第一行两个整数n,m,表示员工总数和代表数;
以下m行,每行2个整数a,b,表示某个代表认为第a号员工奖金应该比第b号员工高。
输出
若无法找到合法方案,则输出“-1”;否则输出一个数表示最少总奖金。
输入样例
reward.in
2 1
1 2
输出样例
reward.out
201
数据范围
80
%
80%
80%的数据满足
n
<
=
1000
,
m
<
=
2000
n<=1000,m<=2000
n<=1000,m<=2000
100
%
100%
100%的数据满足
n
<
=
10000
,
m
<
=
20000
n<=10000,m<=20000
n<=10000,m<=20000
解题思路
这题我们可以用拓扑排序做,若无法完成排序则表示问题无解(存在环);若可以得到完整的拓扑序列,则按序列顺序进行递推即可
程序如下
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
bool pa;
int n,m,x,y,f[100001],k,r[100001],ans,head[100001],in[100001];
struct node
{
int to,next;
}a[100001];
void dfs(int now)//爆搜来半段是否为环,
{
for (int i = head[now]; i; i = a[i].next)
{
int y = a[i].to;
if(!in[y]){
in[y] = 1;
dfs(y);
in[y] = 0;
}
else
{
printf("-1");
pa++;
return ;
}
}
}
void topsort()//拓扑排序模板
{
queue<int>q;
for(int i = 1;i <= n; ++i)
{
if(!r[i])
{
q.push(i);
f[i] = 100;
}
}
while(!q.empty())
{
int t = q.front();
q.pop();
for(int i = head[t]; i; i = a[i].next)
{
f[a[i].to] = max(f[a[i].to], f[t] + 1);
r[a[i].to]--;
if(!r[a[i].to])
q.push(a[i].to);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(in, 0,sizeof(in));
for(int i = 1;i <= m; ++i)
{
scanf("%d%d",&x,&y);
a[++k].to = x;//建图
a[k].next = head[y];
head[y] = k;
r[x]++;
}
dfs(1);
topsort();
for(int i = 1;i <= n; ++i)
ans += f[i];
if (!pa) printf("%d",ans);//判断是否为环,如果不为环就输出
return 0;
}