题目描述
幼儿园里有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。
输入输出样例
说明
【数据范围】
对于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 }
夜空中闪烁的星光,是我心中盛开的光芒。