bzoj2330: [SCOI2011]糖果 (利用差分约束系统将之转换成最长路的问题)
题目
2330: [SCOI2011]糖果 时间限制: 10 Sec 内存限制: 128 MB 题目描述 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。 输入 输入的第一行是两个整数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个小朋友分到的糖果; 输出 输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。 样例输入 5 7 1 1 2 2 3 2 4 4 1 3 4 5 5 4 5 2 3 5 4 5 1 样例输出 11 提示 【数据范围】 对于30%的数据,保证 N<=100 对于100%的数据,保证 N<=100000 对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
这道题的解法呢正如标题所写,可以发现小朋友的关系可以构成不等式,所以我们可以把这些条件利用差分约束系统将其转化为最长路,然后用spfa跑一遍就行了。
附上一个链接:
http://wenku.baidu.com/view/c37d3486bceb19e8b8f6baae.html
#include<stdio.h> #include<string.h> int h,t,l[101010],dd[500000],ccc[101010],cnt,j,n,m,x,y,xx,hh[101010],w,z; long long ans; bool d[101010]; struct node { int next,v,zz; }b[500000]; void add(int aa,int bb,int cc) { b[++cnt].v=bb; b[cnt].next=hh[aa]; b[cnt].zz=cc; hh[aa]=cnt; } bool spfa(int q) { int i; memset(d,0,sizeof(d)); h=0,t=0; l[q]=0;d[q]=true; while(1) { if(h>t)break; for(i=hh[q];i!=0;i=b[i].next) { z=b[i].v; w=b[i].zz; if(l[q]+w>l[z]){ l[z]=l[q]+w; if(d[z])continue; if(++ccc[z]>n)return false; dd[++t]=z; d[z]=true; } } d[q]=false; q=dd[++h]; } return true; } int main() { int i; scanf("%d %d",&n,&m); for(i=1;i<=m;i++) { scanf("%d%d%d",&xx,&x,&y); if(xx==1){add(x,y,0);add(y,x,0);} else if(xx==2)if(x==y){printf("-1\n");return 0;}else add(x,y,1); else if(xx==3)add(y,x,0); else if(xx==4)if(x==y){printf("-1\n");return 0;}else add(y,x,1); else if(xx==5)add(x,y,0); } for(i=n;i>=1;i--) add(0,i,1); if(!spfa(0)){printf("-1\n");return 0;} for(i=1;i<=n;i++) ans+=l[i]; printf("%lld",ans); return 0; }