bzoj 2330[SCOI2011]糖果 - 差分约束
2330: [SCOI2011]糖果
Time Limit: 10 Sec Memory Limit: 128 MBDescription
幼儿园里有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
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
差分约束
这题是要糖果尽可能的少,但是每个人都必须要有
可以通过连边表示不等式关系
比如 A 要比 B 多
就从 B 向 A 连一条权值为 1 的边,这样当我们跑最长路的时候,dis[A] 一定会 >= dis[B] + 1
所以我们只需要把所有的dis初值设为1,放入队列中,跑最长路
如果一个点入队超过n次,就说明进入了循环 (类似 A > B && B > A)
直接输出无解
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 #define LL long long 7 8 using namespace std; 9 10 const int MAXN = 1e5 + 10; 11 const int MAXM = 1e5 + 10; 12 13 queue<int> q; 14 LL ans = 0; 15 int N, K; 16 int cnt = 0; 17 18 int head[MAXN]; 19 LL dis[MAXN]; 20 int flag[MAXN]; 21 int vis[MAXN]; 22 23 inline LL read() 24 { 25 LL x = 0, w = 1; char ch = 0; 26 while(ch < '0' || ch > '9') { 27 if(ch == '-') { 28 w = -1; 29 } 30 ch = getchar(); 31 } 32 while(ch >= '0' && ch <= '9') { 33 x = x * 10 + ch - '0'; 34 ch = getchar(); 35 } 36 return x * w; 37 } 38 39 struct edge { 40 LL v, w; 41 int next; 42 } g[MAXM * 4]; 43 44 void addedge(int u, int v, LL w) 45 { 46 g[++cnt].v = v; 47 g[cnt].w = w; 48 g[cnt].next = head[u]; 49 head[u] = cnt; 50 } 51 52 void SPFA() 53 { 54 while(!q.empty()) { 55 int t = q.front(); 56 vis[t]++; 57 q.pop(); 58 flag[t] = 0; 59 if(vis[t] >= N + 1) { 60 printf("-1\n"); 61 exit(0); 62 } 63 for(int j = head[t]; j; j = g[j].next) { 64 int to = g[j].v; 65 if(dis[to] < dis[t] + g[j].w) { 66 dis[to] = dis[t] + g[j].w; 67 if(!flag[to]) { 68 flag[to] = 1; 69 q.push(to); 70 } 71 } 72 } 73 } 74 } 75 76 int main() 77 { 78 N = read(), K = read(); 79 for(int i = 1; i <= K; i++) { 80 int x = read(), A = read(), B = read(); 81 if(x == 1) { 82 addedge(A, B, 0); 83 addedge(B, A, 0); 84 } else if(x == 2) { 85 addedge(A, B, 1); 86 } else if(x == 3) { 87 addedge(B, A, 0); 88 } else if(x == 4) { 89 addedge(B, A, 1); 90 } else { 91 addedge(A, B, 0); 92 } 93 if(x % 2 == 0 && A == B) { 94 printf("-1"); 95 return 0; 96 } 97 } 98 for(int i = 1; i <= N; i++) { 99 dis[i] = 1; 100 q.push(i); 101 } 102 SPFA(); 103 for(int i = 1; i <= N; i++) { 104 ans += dis[i]; 105 } 106 printf("%lld\n", ans); 107 return 0; 108 }