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
加钱的时候顺序正好反着,可以在加边的时候就倒着加,从而加钱正着加;
两种方法:
第一种好理解;
代码1;
#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> using namespace std; int num;//总边数; int head[10010]; int in[10010]; int mon[10010];//用来存储标号为i的人应该得到的钱数; struct node { int to,next; }a[20010];//数值较大用邻接表; void init() { memset(in,0,sizeof(in)); num=0; memset(head,-1,sizeof(head)); } void add(int u,int v) { a[num].to=v; a[num].next=head[u]; head[u]=num++; in[v]++; } int topo(int n) { queue<int>q; int ans=0,sum=0; while(!q.empty()) q.pop(); for(int j=1;j<=n;j++) { if(in[j]==0) { q.push(j);//先把入度为0的点压入队列; mon[j]=888;//前几个入度为0的点工资最少为888,用数组存起来; } } while(!q.empty()) { int t=q.front(); q.pop(); in[t]=-1; sum+=mon[t];//累加从队列中拿出的元素的钱数; ans++; for(int i=head[t];i!=-1;i=a[i].next) { int b=a[i].to; in[b]--;//删边,即入度减一; if(in[b]==0) { q.push(b); mon[b]=mon[t]+1;//每次在原有基础上加1; } } } if(ans==n)//ans用来记录序列的点的个数,如果排序的点少于n那么信息不足或有冲突; printf("%d\n",sum); else printf("-1\n"); } int main() { int n,m,a,b; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); add(b,a); } topo(n); } return 0; }
代码2:
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include <algorithm> using namespace std; int d[11000], head[11000], n, cnt, a[11000]; struct node { int u, v, w; int next; }edge[22000]; void add(int u, int v, int w) { edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void tops() { int i, j, x, ss=888, ans=0, s=0, flag=0;//ss表示当前层数要加的钱数;ans表示总钱数;s表示当前选的总人数 while(1) { x=0; for(j=1;j<=n;j++) { if(d[j]==0) { a[x++]=j;//记录此层选的人 d[j]--; s++; } } ans+=x*ss; if(x==0&&s<n) { flag=1;//说明出现环,则不能满足要求 break; } if(x==0) break; for(i=0;i<x;i++)//将与该层所有人相连的均降度 { for(j=head[a[i]];j!=-1;j=edge[j].next) { if(edge[j].w==1) { edge[j].w--; d[edge[j].v]--; } } } ss++;//层数递增 } if(flag) printf("-1\n"); else printf("%d\n",ans); } int main() { int m, a, b; while(scanf("%d%d",&n,&m)!=EOF) { memset(d,0,sizeof(d)); memset(head,-1,sizeof(head)); cnt=0; while(m--) { scanf("%d%d",&a,&b); add(b,a,1); d[a]++; } tops(); } return 0; }