码迷,mamicode.com
首页 > 其他好文 > 详细

[SCOI2011]糖果

时间:2018-02-23 23:47:08      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:range   getch   必须   ring   for   math   exit   printf   lin   

题目描述

幼儿园里有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]糖果

标签:range   getch   必须   ring   for   math   exit   printf   lin   

原文地址:https://www.cnblogs.com/adelalove/p/8463601.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!