您的位置:首页 > 理论基础 > 计算机网络

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]。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: