BZOJ 2330 糖果题解
差分约束系统 + SPFA
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2330
Description
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
Input
输入的第一行是两个整数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个小朋友分到的糖果;
Output
输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
Sample Input
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
Sample Output
11
HINT
对于30%的数据,保证 N<=100
对于100%的数据,保证 N<=100000
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
—————————————————————————分割线———————————————————————
将不等式问题转化为图论问题,这里用SPFA 算法解决最长路。
裸题一道,不做过多解释。
代码如下:
1 /************************************************************** 2 Problem: 2330 3 User: shadowland 4 Language: C++ 5 Result: Accepted 6 Time:316 ms 7 Memory:13596 kb 8 ****************************************************************/ 9 #include "bits/stdc++.h" 10 11 using namespace std ; 12 const int maxN = 200010 ; 13 typedef long long QAQ ; 14 15 struct Path { 16 int to , next , w ; 17 }e[ maxN<<2 ]; 18 int Dis[ maxN ] , In [ maxN ] ,p[ maxN ] ; 19 bool visited [ maxN ] ; 20 21 int cnt , N , M ; 22 QAQ ans ; 23 void Add_Edge(const int x,const int y,const int z) 24 { 25 e[++cnt].to=y; 26 e[cnt].next=p[x]; 27 e[cnt].w=z; 28 p[x]=cnt; 29 return ; 30 } 31 bool SPFA (const int S) 32 { 33 int i,t,temp; 34 queue<int> Q; 35 memset(visited,0,sizeof(visited)); 36 memset(Dis,0,sizeof(Dis)); 37 memset(In,0,sizeof(In)); 38 Q.push(S); 39 visited[S]=true; 40 Dis[S]=0; 41 while(!Q.empty()) 42 { 43 t=Q.front();Q.pop();visited[t]=false; 44 for(i=p[t];i!=0;i=e[i].next) 45 { 46 temp=e[i].to; 47 if(Dis[temp]<Dis[t]+e[i].w) 48 { 49 Dis[temp]=Dis[t]+e[i].w; 50 if(!visited[temp]) 51 { 52 Q.push(temp); 53 visited[temp]=true; 54 if(++In[temp]>N)return false; 55 } 56 57 } 58 } 59 } 60 return true ; 61 } 62 int main ( ) { 63 std::ios::sync_with_stdio ( 0 ) ; 64 cin >> N >> M ; 65 for ( int i=1 ; i<=M ; ++i ) { 66 int _ , x , y ; 67 cin >> _ >> x >> y ; 68 if ( _ ==1 ){ 69 Add_Edge ( x , y , 0 ) ; 70 Add_Edge ( y , x , 0 ) ; 71 }else 72 if ( _==2 ) { 73 if ( x==y ) goto Fail ;else 74 Add_Edge ( x , y , 1 ) ; 75 }else 76 if ( _==3 ) { 77 Add_Edge ( y , x , 0 ) ; 78 }else 79 if ( _==4 ) { 80 if ( x==y ) goto Fail ; else 81 Add_Edge ( y , x , 1 ) ; 82 }else 83 { 84 Add_Edge ( x , y , 0 ) ; 85 } 86 } 87 for ( int i=N ; i>=1 ; --i ) 88 Add_Edge ( 0 , i , 1 ) ; 89 if ( !SPFA ( 0 ))goto Fail ; 90 for ( int i=1 ; i<=N ; ++i ) { 91 ans += Dis [ i ] ; 92 } 93 printf ( "%lld\n" , ans ) ; 94 goto End ; 95 Fail: 96 printf ( "-1\n" ) ; 97 End: 98 return 0 ; 99 }
2016-09-14 18:14:40
(完)