[SCOI2011]糖果
題目描述
幼兒園裏有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。
輸入輸出樣例
輸入樣例#1:5 7 1 1 2 2 3 2 4 4 1 3 4 5 5 4 5 2 3 5 4 5 1輸出樣例#1:
11
說明
【數據範圍】
對於30%的數據,保證 N<=100
對於100%的數據,保證 N<=100000
對於所有的數據,保證 K<=100000,1<=X<=5,1<=A, B<=N
解題思路:差分約束
求最小值,>=,最長路
設d[i]為第i個小朋友最少需要的糖果數量
x==1 d[A]==d[B] => d[A]-d[B]<=0,d[B]-d[A]<=0
x==2 d[A]<d[B] => d[B]>d[A] => d[B]>=d[A]+1 => d[B]-d[A]>=1
x==3 d[A]>=d[B] => d[A]-d[B]>=0
x==4 d[A]>d[B] => d[A]>=d[B]+1 => d[A]-d[B]>=1
x==5 d[A]<=d[B] => d[B]>=d[A] => d[B]-d[A]>=0
代碼如下:
1 #include<iostream> 2#include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 #include<cmath> 7 #define ll long long 8 #define inf 1047483600 9 #define mod 317847191 10 using namespace std; 11 inline int read() 12 { 13 int x=0,w=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch==‘-‘) w=-1;ch=getchar();} 15 while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch-‘0‘),ch=getchar(); 16 return x*w; 17 } 18 const int N=10000010; 19 struct node{ 20 int u,v,c,ne; 21 }e[N]; 22 int h[N],tot,n,m; 23 void add(int u,int v,int c) 24 { 25 tot++;e[tot]=(node){u,v,c,h[u]};h[u]=tot; 26 } 27 deque<int>q; 28 int d[N],cnt[N]; 29 bool v[N]; 30 void spfa() 31 { 32 int p1=0,p2=0; 33 for(int i=1;i<=n;++i) 34 { 35 d[i]=1;v[i]=0; 36 q.push_back(i);cnt[i]++; 37 p1++;p2++; 38 } 39 while(!q.empty()) 40 { 41 int ff=q.front();q.pop_front();v[ff]=0; 42 p2--;p1-=d[ff]; 43 for(int i=h[ff];i;i=e[i].ne) 44 { 45 int rr=e[i].v; 46 if(d[rr]<d[ff]+e[i].c) 47 { 48 d[rr]=d[ff]+e[i].c; 49 if(!v[rr]) 50 { 51 if(q.empty() || d[rr]>=d[q.front()] || d[rr]*p2>=p1) q.push_back(rr); 52 else q.push_front(rr); 53 v[rr]=1;p2++;p1+=d[rr]; 54 cnt[rr]++;if(cnt[ff]>=n){cout<<"-1";exit(0);} 55 } 56 } 57 } 58 } 59 ll ans=0; 60 for(int i=1;i<=n;++i) ans+=d[i]; 61 printf("%lld",ans); 62 } 63 int main() 64 { 65 n=read();m=read(); 66 for(int i=1;i<=m;++i) 67 { 68 int x,A,B;x=read();A=read();B=read(); 69 if(x==1) 70 add(A,B,0),add(B,A,0); 71 if(x==2) add(A,B,1); 72 if(x==3) add(B,A,0); 73 if(x==4) add(B,A,1); 74 if(x==5) add(A,B,0); 75 if(x%2==0 && A==B){cout<<"-1";exit(0);} 76 } 77 spfa(); 78 return 0; 79 }
夜空中閃爍的星光,是我心中盛開的光芒。
[SCOI2011]糖果