BZOJ-2330-[SCOI2011]糖果(差分约束)
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
Source
题解
一道裸的差分约束(还不懂差分约束的童鞋可以上百度了解一下)
加完边后,我们设一个虚点把1~n都加一条1的边,跑一下最长路就可以了
不过这道题有一些坑:
1.虚点加边的时候要倒着加,不然会T
2.最后的答案会爆int,要开long long
1 #include<bits/stdc++.h> 2 #define N 100005 3 #define K 100005 4 #define ll long long 5 using namespace std; 6 int n,k,x,a,b,tot; 7 ll ans; 8 int head[N],visit[N]; 9 ll dis[N]; 10 bool flag[N]; 11 int q[10*N]; 12 struct node{ 13 int next,to,dis; 14 }e[3*K]; 15 void add(int x,int y,int z){ 16 e[++tot].next=head[x]; 17 head[x]=tot; 18 e[tot].to=y; 19 e[tot].dis=z; 20 } 21 bool spfa(){ 22 for (int i=1;i<=n;i++) flag[i]=false,visit[i]=0; 23 int t=1,w=1; 24 q[1]=0; flag[0]=true; visit[0]=1; 25 while (t<=w){ 26 int k=q[t]; 27 for (int i=head[k];i;i=e[i].next){ 28 int v=e[i].to; 29 if (dis[v]<dis[k]+e[i].dis){ 30 dis[v]=dis[k]+e[i].dis; 31 if (!flag[v]){ 32 visit[v]++; 33 if (visit[v]>n) return false; 34 flag[v]=true; 35 q[++w]=v; 36 if (dis[q[w]]<dis[q[t+1]]) swap(q[w],q[t+1]); 37 } 38 } 39 } 40 flag[k]=false; 41 t++; 42 } 43 return true; 44 } 45 int main(){ 46 scanf("%d%d",&n,&k); 47 for (int i=1;i<=k;i++){ 48 scanf("%d%d%d",&x,&a,&b); 49 if (!(x&1)&&a==b){ 50 puts("-1"); 51 return 0; 52 } 53 switch (x){ 54 case 1:add(a,b,0);add(b,a,0);break; 55 case 2:add(a,b,1);break; 56 case 3:add(b,a,0);break; 57 case 4:add(b,a,1);break; 58 case 5:add(a,b,0);break; 59 } 60 } 61 for (int i=n;i>=1;i--) add(0,i,1); 62 if (!spfa()){ 63 puts("-1"); 64 return 0; 65 } 66 for (int i=1;i<=n;i++) ans+=dis[i]; 67 printf("%lld\n",ans); 68 return 0; 69 }