P3275 [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
话说出题人真是用(sang)心(xin)良(bing)苦(kuang)
差分约束卡SPFA。。
我还能说什么。。
=.=、、、、、、
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #include<algorithm> 7 #include<cstdlib> 8 #define lli int 9 using namespace std; 10 const int MAXN=233333; 11 inline void read(int &n) 12 { 13 char c='+';int x=0,flag=1; 14 while(c<'0'||c>'9') 15 {c=getchar();if(c=='-')flag=-1;} 16 while(c>='0'&&c<='9') 17 {x=x*10+c-48;c=getchar();} 18 n=(x*flag); 19 } 20 int n,m; 21 struct node 22 { 23 int u,v,w,nxt; 24 }edge[MAXN]; 25 int head[MAXN]; 26 int num=1; 27 inline void no_ans() 28 { 29 printf("-1"); 30 exit(0); 31 } 32 inline void add_edge(int x,int y,int z) 33 { 34 edge[num].u=x; 35 edge[num].v=y; 36 edge[num].w=z; 37 edge[num].nxt=head[x]; 38 head[x]=num++; 39 } 40 int dis[MAXN]; 41 int vis[MAXN]; 42 int happen[MAXN]; 43 inline bool SPFA(int p) 44 { 45 if(happen[p]>n) 46 no_ans(); 47 vis[p]=1; 48 for(register int i=head[p];i!=-1;i=edge[i].nxt) 49 { 50 if(dis[edge[i].v]>dis[edge[i].u]+edge[i].w) 51 { 52 dis[edge[i].v]=dis[edge[i].u]+edge[i].w; 53 happen[edge[i].v]++; 54 if(vis[edge[i].v]||!SPFA(edge[i].v)) 55 return false; 56 } 57 } 58 vis[p]=0; 59 return true; 60 } 61 int main() 62 { 63 memset(dis,0x3f,sizeof(dis)); 64 memset(head,-1,sizeof(head)); 65 read(n);read(m); 66 for(register int i=n;i>=1;--i) 67 add_edge(0,i,-1); 68 for(register int i=1;i<=m;++i) 69 { 70 int how,a,b; 71 read(how);read(a);read(b); 72 if(how==1) 73 { 74 add_edge(b,a,0);add_edge(a,b,0); 75 } 76 else if(how==2) 77 { 78 if(a==b)no_ans(); 79 add_edge(a,b,-1); 80 } 81 else if(how==3) 82 add_edge(b,a,0); 83 else if(how==4) 84 add_edge(b,a,-1); 85 else if(how==5) 86 add_edge(a,b,0); 87 } 88 dis[0]=0; 89 long long int ans=0; 90 if(SPFA(0)) 91 { 92 for(register int i=1;i<=n;++i) 93 ans-=dis[i]; 94 } 95 else no_ans(); 96 printf("%lld",ans); 97 return 0; 98 }
作者:自为风月马前卒
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。