1. 程式人生 > >[SCOI2011]糖果

[SCOI2011]糖果

class push radi radius ace main 個數 朋友 dig

題目描述

幼兒園裏有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]糖果