题目:
Reward
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9224 Accepted Submission(s): 2942
Problem Description
Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards.
The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.
The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.
Input
One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000)
then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.
then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.
Output
For every case ,print the least money dandelion 's uncle needs to distribute .If it's impossible to fulfill all the works' demands ,print -1.
Sample Input
2 1 1 2 2 2 1 2 2 1
Sample Output
1777 -1
Author
dandelion
Source
Recommend
又是一道拓扑排序的题,在这因为要发奖金而且前面人的奖金大于后面人的奖金,这时候我们需要反向建边,最后判环,有环的时候输出-1,利用path来存储比888大的多少的数,最后算出sum+888*n就好了
关于反向建边的原因:
分析,根据题意可以得出一个拓扑的关系,比如 一组数据:
4 4
1 2
1 3
2 4
3 4
那么有如图关系:(位于上层的要求比下层的高)
由图可以知道,我们需要给1号890,2、3号889,4号888元,但是我们在拓扑排序的时候总是从入度为0的点 (从图中也就是1号) 开始,如果这样那么我们怎么知道 入度为 0 的点是在第几层呢?那么同样也不好计算总共的奖金数量。
在这里我用的是反向建边,那么建立之后 对于上案例如图:
如此的时候,我们在拓扑排序的时候第一次找到的点就是没有要求的工人,那么奖励就直接加888,再考虑这一层之后让基本奖励 + 1 ,再拓扑排序便可以了
来自: http://blog.csdn.net/zyy173533832/article/details/11483505代码:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 1000007
#define N 20100
#define M 100000+50
#define ll long long
using namespace std;
int n,m,len,k=0;
int first[N],vis[N],path[N];
struct node
{
int u,v,next;
}G[N];
void add_edge(int u,int v)
{
G[len].v=v;
G[len].next=first[u];
first[u]=len++;
}
void toposort()
{
mem(path,0);
stack<int>s;
for(int i=1;i<=n;i++)
if(!vis[i])
s.push(i);
while(!s.empty())
{
int u=s.top();
s.pop();
for(int i=first[u];~i;i=G[i].next)
{
int v=G[i].v;
path[v]=max(path[v],path[u]+1);
vis[v]--;
if(!vis[v])
s.push(v);
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
len=1;
mem(first,-1);
mem(vis,0);
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add_edge(y,x);
vis[x]++;
}
toposort();
int sum=0,flag=0;
for(int i=1;i<=n;i++)
{
if(vis[i])
{
flag=1;
break;
}
sum+=path[i];
}
if(flag)puts("-1");
else printf("%d\n",sum+888*n);
}
return 0;
}