拓扑排序(1)--hdu2647(拓扑排序邻接表模板 应用判断是否存在环)

来源:互联网 发布:水公主为什么离开网络 编辑:程序博客网 时间:2024/05/21 17:38

                                            Reward

                                                       Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)



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 11 22 21 22 1
 

Sample Output
1777-1
 

Author
dandelion
 

Source
曾是惊鸿照影来

题意:
老板要给很多员工发奖金, 但是部分员工有个虚伪心态, 认为自己的奖金必须比某些人高才心理平衡; 但是老板很人道, 想满足所有人的要求, 并且很吝啬,想花的钱最少
输入若干个关系
a b
a c
c b
意味着a 的工资必须比b的工资高 同时a 的工资比c高; c的工资比b高
当出现环的时候输出-1


这道题不能用矩阵表示,因为1w*1w绝对超内存,分析数据,前一个a的钱要多于后一个b,所以我们要把b作为出度,a为入度,如果不明白这个地方,举例:b——>a——>c——>d ,b为888,钱数逐渐上升,如果反过来a为出度就不符合题意啦。。。


还有一个地方需要注意:判断输出-1的情况不能只判断没有一个入度为0的点,因为有可能在中间就出现矛盾了,如:a——>b——>c——>d——>c 有入度为0的点,但却要输出-1;代码:
#include<iostream>#include<cstring>#include<queue>#include<cstdio>using namespace std;#define MAX 10005int n,sum,ans;int into[MAX],head[MAX],money[MAX];struct Reward{    int to;    int next;} edge[2*MAX];void topu(){    int i,j,l,v;    queue<int>Q;    for(i=1; i<=n; i++)        if(into[i]==0)            Q.push(i);//把入度为0的点压如队列    while(!Q.empty())    {        v=Q.front();//调用首位元素        sum+=money[v];        Q.pop();//出队        ans++; //用一个变量记录调用元素的总量,最后与n作比较        for(l=head[v]; l!=-1; l=edge[l].next)//与队首元素v有关的都枚举一遍        {            if(--into[edge[l].to]==0)//如果入度-1为0,即为v的下一个元素            {                Q.push(edge[l].to);//将其压入队列                money[edge[l].to]=money[v]+1;//保证后一个要比前一个多1            }        }    }}int main(){    int m,a,b,tot;    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(head,-1,sizeof(head));        memset(into,0,sizeof(into));        for(int i=1; i<=n; i++)            money[i]=888;//所有人一开始都为888        tot=0;        sum=0;        ans=0;        while(m--)        {            scanf("%d%d",&a,&b);//注意要逆过来,因为后一个b是基础的888,应当作为出度            edge[tot].to=a;            edge[tot].next=head[b];            head[b]=tot++;            into[a]++;//记录入度        }        topu();        if(ans!=n)//有可能在中间出现矛盾,必须保证每个地方都不矛盾            sum=-1;        cout<<sum<<endl;    }}




1 0
原创粉丝点击