【BZOJ2330】【SCOI2011】糖果 [差分约束]
2330: [SCOI2011]糖果
Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss]
Description
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
Input
输入的第一行是两个整数N,K。
接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。
如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;
如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;
如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;
如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;
如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;
Output
输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
Sample Input
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
Sample Output
11
HINT
对于30%的数据,保证 N<=100
对于100%的数据,保证 N<=100000
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
Main idea
有若干个小朋友分糖果,要求每个人至少分到一颗糖,给出若干个数之间大小或者等于的限制,求最少需要多少个糖果可以满足条件。
Solution
发现有若干限制大小,那么我们想到了差分约束系统,在两点之间连一条带权边,根据限制条件决定边权。因为要满足所有情况,我们先将所有点入队,跑一遍最长路即可求出答案。
Code
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 using namespace std; 8 9 const int ONE=200001; 10 const int INF=2147483640; 11 12 int n,m; 13 int PD,x,y; 14 int next[ONE],first[ONE],go[ONE],tot; 15 int w[ONE]; 16 int dist[100001]; 17 int vis[100001],q[1000001],tou,wei; 18 long long Ans; 19 int Take_ring[100001]; 20 21 int get() 22 { 23 int res,Q=1; char c; 24 while( (c=getchar())<48 || c>57) 25 if(c=='-')Q=-1; 26 if(Q) res=c-48; 27 while((c=getchar())>=48 && c<=57) 28 res=res*10+c-48; 29 return res*Q; 30 } 31 32 int Add(int u,int v,int z) 33 { 34 next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z; 35 } 36 37 void PD_same(int x,int y) 38 { 39 if(x==y) 40 { 41 printf("-1"); 42 exit(0); 43 } 44 } 45 46 int Spfa() 47 { 48 while(tou<wei) 49 { 50 int u=q[++tou]; 51 for(int e=first[u];e;e=next[e]) 52 { 53 int v=go[e]; 54 if(dist[v]<dist[u]+w[e]) 55 { 56 if(++Take_ring[v]>=n) return 0; 57 dist[v]=dist[u]+w[e]; 58 if(!vis[v]) 59 { 60 vis[v]=1; 61 q[++wei]=v; 62 } 63 } 64 } 65 vis[u]=0; 66 } 67 return 1; 68 } 69 70 int main() 71 { 72 n=get(); m=get(); 73 for(int i=1;i<=m;i++) 74 { 75 PD=get(); x=get(); y=get(); 76 if(PD==1) Add(x,y,0),Add(y,x,0); 77 if(PD==2) Add(x,y,1),PD_same(x,y); 78 if(PD==3) Add(y,x,0); 79 if(PD==4) Add(y,x,1),PD_same(x,y); 80 if(PD==5) Add(x,y,0); 81 } 82 83 for(int i=1;i<=n;i++) 84 { 85 dist[i]=vis[i]=1; 86 q[++wei]=i; 87 } 88 89 if(!Spfa()) 90 { 91 printf("-1"); 92 return 0; 93 } 94 for(int i=1;i<=n;i++) 95 Ans+=(long long)dist[i]; 96 printf("%lld",Ans); 97 98 }