hdu - 4322 - Candy - 网络流
2012-10-21 15:34
483 查看
题意:http://acm.hdu.edu.cn/showproblem.php?pid=4322
like[i][j]表示第i个孩子喜欢第j个糖果(总共m个孩子,n个糖)。 如果孩子拿到他喜欢的糖果,那么他将会增加k个欢乐值;拿到不喜欢的,增加1。 如果孩子i的欢乐值大于B[i],那么他才是开心的。
问,能否有一种分配方案,让所有孩子都开心。
解:
首先声明,由于被小孩子不喜欢的糖果的对小孩产生的效力是一样的,所以我们在网络流的时候先不考虑。
1 - 源点0到1~N个糖果,容量为1,费用为0
2 - 根据like数组,like[i][j] == 1时在糖果j和人N+i之间建立有一条边,容量为1,费用为0
3*- 根据b[i]和K的值建立小孩和汇点之间的边:
如果b[i] 是 K 的倍数, 说明花费b[i] / K个喜欢的糖果可以达到b[i],建立一条边,费用为K,容量为b[i] / K;
否则,将这条边拆为两部分,第一部分是b[i] / K的部分,第二部分根据b[i] % K的部分。(如果b[i] % k == 0,说明b[i]是k的倍数;
若b[i] % k == 1, 特殊糖果和一般糖果价值一样,没必要当做特殊糖果处理)
建好图后,求最大费用最大流(只需将费用改为负的,然后套最小费用最大流即可).。得出特殊糖果匹配b[i]的最大值。看剩余的普通糖果是否满足缺少的b[i]。
like[i][j]表示第i个孩子喜欢第j个糖果(总共m个孩子,n个糖)。 如果孩子拿到他喜欢的糖果,那么他将会增加k个欢乐值;拿到不喜欢的,增加1。 如果孩子i的欢乐值大于B[i],那么他才是开心的。
问,能否有一种分配方案,让所有孩子都开心。
解:
首先声明,由于被小孩子不喜欢的糖果的对小孩产生的效力是一样的,所以我们在网络流的时候先不考虑。
1 - 源点0到1~N个糖果,容量为1,费用为0
2 - 根据like数组,like[i][j] == 1时在糖果j和人N+i之间建立有一条边,容量为1,费用为0
3*- 根据b[i]和K的值建立小孩和汇点之间的边:
如果b[i] 是 K 的倍数, 说明花费b[i] / K个喜欢的糖果可以达到b[i],建立一条边,费用为K,容量为b[i] / K;
否则,将这条边拆为两部分,第一部分是b[i] / K的部分,第二部分根据b[i] % K的部分。(如果b[i] % k == 0,说明b[i]是k的倍数;
若b[i] % k == 1, 特殊糖果和一般糖果价值一样,没必要当做特殊糖果处理)
建好图后,求最大费用最大流(只需将费用改为负的,然后套最小费用最大流即可).。得出特殊糖果匹配b[i]的最大值。看剩余的普通糖果是否满足缺少的b[i]。
#include <cstring> #include <cstdio> const int maxn = 100; const int maxm = maxn * maxn * 2; const int inf = 1000000000; int n, m, k; int b[maxn], sumB; int c[maxn][maxn]; int src, des; struct Edge{ int u, v, w, f, nxt; }edge[maxm]; int edgeNum, head[maxn]; inline void initEdge(){ edgeNum = 0; memset(head, - 1, sizeof(head)); } inline void addEdgeSub(int u, int v, int w, int f){ edge[edgeNum].u = u; edge[edgeNum].v = v; edge[edgeNum].w = w; edge[edgeNum].f = f; edge[edgeNum].nxt = head[u]; head[u] = edgeNum ++; } inline void addEdge(int u, int v, int w, int f){ addEdgeSub(u,v,w,f); addEdgeSub(v,u,-w,0); } void buildGraph(){ initEdge(); src = 0; des = n + m + 1; for(int i = 0; i < n; i ++){ addEdge(src, i + 1, 0, 1); } for(int i = 0; i < m; i ++){ for(int j = 0; j < n; j ++){ if(c[i][j]){ addEdge(j + 1, i + n + 1,0,1);// } } addEdge(i + n + 1, des, k, b[i] / k); if(b[i] % k > 1){ addEdge(i + n + 1, des, b[i] % k, 1); } } } int dis[maxn]; int queue[maxn]; bool vis[maxn]; int back[maxn]; bool bfs(){ int front = 0, rear = 1; memset(vis, false, sizeof(vis)); memset(dis, -1, sizeof(dis)); queue[0] = src; dis[src] = 0; vis[src] = true; back[src] = -1; bool flag = false; while(front != rear){ int u = queue[front]; for(int i = head[u]; i != -1; i = edge[i].nxt){ int v = edge[i].v; int w = edge[i].w; if(edge[i].f){ if(dis[v] < dis[u] + w){ dis[v] = dis[u] + w; back[v] = i; if(!vis[v]){ vis[v] = true; queue[rear] = v; if(++ rear >= maxn){ rear = 0; } } } } } vis[u] = false; if(++ front >= maxn){ front = 0; } } return dis[des] != -1; } int getFlow(){ int tmp = des; int Min = inf; while(back[tmp] != -1){ if(edge[back[tmp]].f < Min){ Min = edge[back[tmp]].f; } tmp = edge[back[tmp]].u; } tmp = des; while(back[tmp] != -1){ edge[back[tmp]].f -= Min; edge[back[tmp] ^ 1].f += Min; tmp = edge[back[tmp]].u; } return Min; } bool judge(){ int cost = 0, flow = 0; while(bfs()){ cost += dis[des]; flow += getFlow(); } return n - flow >= sumB - cost; } int main(){ int T; scanf("%d",&T); for(int ca = 1; ca <= T; ca ++){ scanf("%d%d%d",&n,&m,&k); sumB = 0; for(int i = 0; i < m; i ++){ scanf("%d",&b [i]); sumB += b[i]; } for(int i = 0; i < m; i ++){ for(int j = 0; j < n; j ++){ scanf("%d",&c[i][j]); } } buildGraph(); printf("Case #%d: ",ca); if(judge()) puts("YES"); else puts("NO"); } return 0; }
相关文章推荐
- hdu 4322 Candy 费用流
- HDU 4322-Candy
- hdu 4322 Candy 费用流
- HDU 4322 Candy
- HDU 4322 Candy 最大费用流
- 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 【多校3】【费用流】
- 【HDU】4322 Candy 【最小费用流——给每条边一个被流优先级】
- HDU 4322 Candy
- 平面图网络流(poj 2822 & hdu 4280 )
- 【网络流】 HDU 3998 Sequence 最多不重合路径
- hdu-4309(网络流)
- joj 2453 candy 网络流建图的题
- HDU 4280 网络流(ISAP || Dinic)