bzoj2330 [SCOI2011]糖果
2330: [SCOI2011]糖果
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6415 Solved: 2120
[Submit][Status][Discuss]
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老師至少需要準備的糖果數,如果不能滿足小朋友們的所有要求,就輸出
Sample Input
5 71 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
Source
Day1
分析:比較明顯的一道差分約束系統的題,這類題一般是這樣的:如果要求差值最大,那麽轉換成小於等於號的式子,然後求最短路,如果要求差值最小,那麽轉換成大於等於號,求最長路.
1: A == B,那麽A >= B, B >= A,分別連邊(A,B,0)、(B,A,0).
2: A < B等價於A <= B-1,連邊(A,B,1).
3: A >= B,連邊(B,A,0).
4: A > B等價於B <= A - 1,連邊(B,A,1).
5: A <= B,連邊(A,B,0).
然後跑一下spfa判一下負環就能過了.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; int n,k; int head[100010],to[200010],nextt[200010],w[200010],tot,cnt[100010]; long long ans,d[100010]; bool vis[100010]; void add(int x,int y,int z) { w[tot] = z; to[tot] = y; nextt[tot] = head[x]; head[x] = tot++; } bool spfa() { queue <int> q; for (int i = 1; i <= n; i++) { d[i] = 1; vis[i] = true; q.push(i); } while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u]; i + 1; i = nextt[i]) { int v = to[i]; if (d[v] < d[u] + w[i]) { d[v] = d[u] + w[i]; if (!vis[v]) { ++cnt[v]; if (cnt[v] >= n) return false; vis[v] = 1; q.push(v); } } } } return true; } int main() { memset(head,-1,sizeof(head)); scanf("%d%d",&n,&k); for (int i = 1; i <= k; i++) { int x,a,b; scanf("%d%d%d",&x,&a,&b); if (x == 1) { add(a,b,0); add(b,a,0); } if (x == 2) { add(a,b,1); } if (x == 3) { add(b,a,0); } if (x == 4) { add(b,a,1); } if (x == 5) { add(a,b,0); } } if (!spfa()) printf("-1\n"); else { for (int i = 1; i <= n; i++) ans += d[i]; printf("%lld\n",ans); } return 0; }
bzoj2330 [SCOI2011]糖果