HDU 4322 Candy
2013-10-26 18:27
357 查看
题意:老师要把N颗糖分给M个小盆友,M*N的矩阵中的元素(i,j)表示第i个小孩对第j颗糖的喜好,1表示喜欢,0表示不喜欢。如果一个小朋友得到了一颗糖,并且这颗糖是自己喜欢的糖,他会得到K个glad值,否则,只能得到1的glad值。现在告诉你每个小朋友i的glad值要达到B[i]才会开心,问是否存在一种分配方案使得所有的小朋友都能够开心。(1<=N<=13, 1<=M<=13, 2<=K<=10)
记得以前做过一个哈工大OJ上的题,是《网络流建模汇总》上面的例题。也是分糖果的,那个题是说,如果一个孩子被分到了一颗喜欢的糖,glad值+2,如果被分到一颗不喜欢的,glad值+1。那个题采用了这么一种做法:把所有的glad值-1,那么图中的边的容量就只有0和1了,求出最大流maxflow以后,直接判断maxflow+n(糖果数目)>sum(B[i])是不是成立,如果成立就可以给出一个分配方案。maxflow流的意义是所有孩子被分到喜欢的糖的前提下的最大的glad值之和-这些孩子喜欢的糖的数目,那么再加上所有糖的数目n就是能够总体能够达到最大glad值了。
这里,glad值的范围变成了[2,10],其实做法还是差不多的。
首先建立源点S和汇点T,从S出发向每颗糖i连一条(S,i,K-1)的边。如果第i颗糖可以被小朋友j喜欢,则连一条边(i,j,K-1)。最关键的是从小朋友到汇点T的边应该怎么连。
对于每个小朋友的最小满意度,若B[i]%K>1,连一条(i,T,B[i]%K-1)的边。另外,连一条(i,T,B[i]/K*(K-1) )的边。这样网络中最大流maxflow的意义就是所有孩子被分到喜欢的糖的前提下的最大的glad值之和-这些孩子喜欢的糖的数目了。最后比较maxflow+N和sum(B[i])的大小就可以了。
View Code
记得以前做过一个哈工大OJ上的题,是《网络流建模汇总》上面的例题。也是分糖果的,那个题是说,如果一个孩子被分到了一颗喜欢的糖,glad值+2,如果被分到一颗不喜欢的,glad值+1。那个题采用了这么一种做法:把所有的glad值-1,那么图中的边的容量就只有0和1了,求出最大流maxflow以后,直接判断maxflow+n(糖果数目)>sum(B[i])是不是成立,如果成立就可以给出一个分配方案。maxflow流的意义是所有孩子被分到喜欢的糖的前提下的最大的glad值之和-这些孩子喜欢的糖的数目,那么再加上所有糖的数目n就是能够总体能够达到最大glad值了。
这里,glad值的范围变成了[2,10],其实做法还是差不多的。
首先建立源点S和汇点T,从S出发向每颗糖i连一条(S,i,K-1)的边。如果第i颗糖可以被小朋友j喜欢,则连一条边(i,j,K-1)。最关键的是从小朋友到汇点T的边应该怎么连。
对于每个小朋友的最小满意度,若B[i]%K>1,连一条(i,T,B[i]%K-1)的边。另外,连一条(i,T,B[i]/K*(K-1) )的边。这样网络中最大流maxflow的意义就是所有孩子被分到喜欢的糖的前提下的最大的glad值之和-这些孩子喜欢的糖的数目了。最后比较maxflow+N和sum(B[i])的大小就可以了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define INF 1<<30 #define maxn 30 #define maxm 900 using namespace std; int v[maxm],next[maxm],w[maxm]; int first[maxn],d[maxn],work[maxn],q[maxn]; int e,S,T; int like[14][14]; void init(){ e = 0; memset(first,-1,sizeof(first)); } void add_edge(int a,int b,int c){ //printf("add:%d to %d,cap = %d\n",a,b,c); v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++; v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++; } int bfs(){ int rear = 0; memset(d,-1,sizeof(d)); d[S] = 0;q[rear++] = S; for(int i = 0;i < rear;i++){ for(int j = first[q[i]];j != -1;j = next[j]) if(w[j] && d[v[j]] == -1){ d[v[j]] = d[q[i]] + 1; q[rear++] = v[j]; if(v[j] == T) return 1; } } return 0; } int dfs(int cur,int a){ if(cur == T) return a; for(int &i = work[cur];i != -1;i = next[i]){ if(w[i] && d[v[i]] == d[cur] + 1) if(int t = dfs(v[i],min(a,w[i]))){ w[i] -= t;w[i^1] += t; return t; } } return 0; } int dinic(){ int ans = 0; while(bfs()){ memcpy(work,first,sizeof(first)); while(int t = dfs(S,INF)) ans += t; } return ans; } int main() { int N,M,K,nkase; scanf("%d",&nkase); for(int kase = 1;kase <= nkase;kase++){ init(); scanf("%d%d%d",&N,&M,&K); S = 0,T = N+M+1; int sum = 0,B; for(int i = 1;i <= N;i++) add_edge(S,i,K-1); for(int i = 1;i <= M;i++){ scanf("%d",&B); sum += B; if(B%K > 1) add_edge(N+i,T,B%K-1); add_edge(N+i,T,B/K*(K-1)); } for(int i = 1;i <= M;i++){//M个小孩 for(int j = 1;j <= N;j++){//N颗糖 scanf("%d",&like[i][j]); if(like[i][j]) add_edge(j,i+N,K-1); } } int maxflow = dinic(); //printf("maxflow = %d\n",maxflow); if(maxflow + N >= sum) printf("Case #%d: YES\n",kase); else printf("Case #%d: NO\n",kase); } return 0; }
View Code
相关文章推荐
- HDU 4322-Candy
- HDU-4322-Candy
- hdu 4322 Candy 【最大费用最大流】
- HDU 4322 Candy 最大费用流+巧妙建图
- hdu-4322-Candy-费用流
- hdu 4322 Candy(最大费用流)2012 Multi-University Training Contest 3
- hdu 4322 Candy 最大费用最大流
- HDU 4322 Candy (最大费用最大流)经典
- hdu 4322 Candy 【多校3】【费用流】
- HDU 4322 Candy 最大费用流
- 【HDU】4322 Candy 【最小费用流——给每条边一个被流优先级】
- hdu 4322 Candy 费用流
- hdu 4322 Candy 费用流
- HDU 4322 Candy
- hdu - 4322 - Candy - 网络流
- HDU 4465 - Candy(概率与数学优化)
- HDU 5654 xiaoxin and his watermelon candy 离线树状数组 区间不同数的个数
- 【HDOJ】4322 Candy
- [概率+对数优化] hdu 4465 Candy
- 杭电 HDU 1034 Candy Sharing Game