Reward
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7413 Accepted Submission(s): 2328
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.
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.
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
1.题意:老板要发工资,有的人可能对工资有所要求,即一定要超过某一个人,每个人最少的工资是888,给出工人人数和某些人的要求,求老板最少发多少工资;
2.思路:把每个人都看成点,要求看成边,转化成又向图存起来用逆向(也可叫正向,看如何选择关系了,这里只是做提示)拓扑排序找出最低工资的人,以后每次去掉一点都比前面的工资多一,递推出所有人的最小工资保存在数组中,再累加起来即为答案;
3.失误: 如果输入数据没有输出,而且还不结束,那就是死循环了,一般都在循环处发生,可以调试看问题所在点,也可能是数据方面的问题:赋值错误或没有赋值;函数没有返回等。
4.代码如下:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=1e6+10;
int rew[MAXN],head[MAXN],ideg[MAXN];
int en,sum;
struct Edge{
int to;
int next;
}edge[MAXN];
void init()
{
memset(head,-1,sizeof(head)); en=0;
}
void addedge(int u,int v)
{
Edge E={v,head[u]};
edge[en]=E;//不赋值 死循环
head[u]=en++;
}
void topo(int n)
{
queue<int> que;
for(int i=1;i<=n;++i)
{
if(!ideg[i])//只要放进队 就应标记即度数-1
{
rew[i]=888; que.push(i);
// ideg[i]=-1;有些情况不可思议但一定要标记 有向图可能没影响 但无向图一定有影响
}
}
sum=0;
while(!que.empty())
{
++sum;//放进队列的总元素 只有产生环的情况下与环相关的点度数都不为0
int now=que.front(); que.pop();
for(int i=head[now];i!=-1;i=edge[i].next)
{
int go=edge[i].to;
if(ideg[go]>0) --ideg[go];//死循环
if(!ideg[go])
{
rew[go]=rew[now]+1;
que.push(go);//放进队标记 一个元素只能放进一次队列
//ideg[go]=-1;
}
}
}
}
int main()
{
int n,i,m,ans,u,v;
while(~scanf("%d %d",&n,&m))
{
init(); memset(ideg,0,sizeof(ideg));
for(i=1;i<=m;++i)
{
scanf("%d %d",&u,&v);
addedge(v,u);
++ideg[u];
}
// if(m>n-1) 任何情况下都要考虑多重边 太坑
// {
// printf("-1\n"); continue;
// }
topo(n); ans=0;
if(sum!=n)
{
printf("-1\n"); continue;
}
for(i=1;i<=n;++i)
ans+=rew[i];
printf("%d\n",ans);
}
return 0;
}