题意:
给出猪圈个数 m 和买家人数 n
然后给出m个猪圈的猪的头数..
接下来 n 行..
给出mm a1 a2 .. a(mm) k 例如 2 1 5 3 表示第i+1个用户 有mm(2) 个猪圈的钥匙 就是有第 a1(1) 个和第 a2(5) 个猪圈的钥匙..还想要买得k头猪..
问最多能够卖出多少头..
思路:
其实就是最大流~
唯一有趣的是建图的过程..
/************************************/
建一个超级源点0..超级汇点n+1
以客户作为节点..
超级源点根据第一个拥有猪圈的客户和超级源点连线..容量就是第一个客户累计可以得到多少头猪..
因为第一个打开猪圈的客户可以取得所有的猪..所以超级源点和客户之间的连线容量就表示第一个打开猪圈的人虽能够得到的数量..
然后接下来的每一个人与前一个打开猪圈的人之间连线..容量为INF..因为可以从别的猪圈调猪过来..
然后求得的最大流就是可以卖得的猪的数量..
/**********************************/
Tips:
很喜欢这道题建图的技巧~感觉很有才~~~很聪明~~虽然..可能很基础~
大体就是上面说的了~其中用到了last数组来记录该猪圈上一个拥有钥匙的人~
Code:
View Code
1 #include <stdio.h> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 #define clr(x) memset(x, 0, sizeof(x)) 7 const int INF = 0x1f1f1f1f; 8 const int MAXN = 110; 9 10 int cap[MAXN][MAXN], flow[MAXN][MAXN]; 11 int p[MAXN], a[MAXN]; 12 int f, n; 13 14 void EK(int s, int t) 15 { 16 queue<int> q; 17 memset(flow, 0, sizeof(flow)); 18 memset(a, 0, sizeof(a)); 19 memset(p, 0, sizeof(p)); 20 f = 0; 21 while(1) 22 { 23 memset(a, 0, sizeof(a)); 24 a[s] = INF; 25 q.push(s); 26 while(!q.empty()) 27 { 28 int u = q.front(); 29 q.pop(); 30 for(int v = 0; v <= n+1; ++v) 31 if(!a[v] && cap[u][v] > flow[u][v]) 32 { 33 p[v] = u; 34 q.push(v); 35 a[v] = a[u] < cap[u][v] - flow[u][v]? a[u]:cap[u][v] - flow[u][v]; 36 } 37 } 38 if(a[t] == 0) break; 39 for(int u = t; u != s; u = p[u]) 40 { 41 flow[p[u]][u] += a[t]; 42 flow[u][p[u]] -= a[t]; 43 } 44 f += a[t]; 45 } 46 } 47 48 49 int main() 50 { 51 int i, j, k; 52 int nn, mm; 53 int tmp, m; 54 int s, t; 55 int h[1010]; 56 int last[1010]; 57 58 while(scanf("%d %d", &mm, &nn) != EOF) 59 { 60 clr(cap); 61 clr(last); 62 s = 0, t = nn+1; 63 n = nn; 64 65 for(i = 1; i <= mm; ++i) 66 scanf("%d", &h[i]); 67 68 for(i = 1; i <= nn; ++i){ 69 scanf("%d", &m); 70 for(j = 0; j < m; ++j){ 71 scanf("%d", &tmp); 72 if(last[tmp] == 0) 73 cap[s][i] += h[tmp]; 74 else 75 cap[last[tmp]][i] = INF; 76 last[tmp] = i; 77 } 78 scanf("%d", &cap[i][t]); 79 } 80 81 EK(s, t); 82 printf("%d\n", f); 83 } 84 return 0; 85 }