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

分配问题[网络流24题之18]

2016-05-24 13:27 405 查看

问题描述:

有 n 件工作要分配给 n 个人做。第 i 个人做第 j 件工作产生的效益为 cij 。试设计一个将 n 件工作分配给 n 个人做的分配方案,使产生的总效益最大。

编程任务:

对于给定的 n 件工作和 n 个人,计算最优分配方案和最差分配方案。

数据输入:

第 1 行有 1 个正整数 n,表示有 n 件工作要分配给 n 个人做。接下来的 n 行中,每行有 n 个整数 cij , 1≤i≤n , 1≤j≤n ,表示第 i 个人做第 j 件工作产生的效益为 cij 。

结果输出:

输出共两行,第 1 行为最小总效益,第 2 行为最大总效益

输入文件示例:

5

2 2 2 1 2

2 3 1 2 4

2 0 1 1 1

2 3 4 3 3

3 2 1 2 1

输出文件示例:

5

14

分析:

这一道裸地最小费用最大流问题,基本思路是像寻找最短路径一样每次寻找最小的花费,每寻找到一条就做一个调整,直到不存在路径为止;最大流就是直接把所有边权全部取负再进行以上操作即可。

代码:

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

const int inf = 0x3f3f3f3f;

int n,m;
int head[147],nxt[11447],to[11447],wei[11447],cost[11447],tot=1;
queue<int >que;
int dis[147],pre[147],pres[147];
bool vis[147];
int used;

void add(int,int,int);
bool bfs();
void dinic();

int main(){

scanf("%d",&n);
for(int i=1;i<=n;++i)
add(145,i,0);
for(int i=1;i<=n;++i)
add(i+n,146,0);
for(int i=1,a;i<=n;++i)
for(int j=1;j<=n;++j){
scanf("%d",&a);
add(i,j+n,a);
}

used = 0;
while(bfs())
dinic();
printf("%d\n",used);

for(int i=2;i<tot;i+=2){
wei[i] += wei[i^1];
wei[i^1] = 0;
cost[i] = -cost[i];
cost[i^1] = -cost[i^1];
}

used = 0;
while(bfs())
dinic();
printf("%d",-used);

return 0;

}

void add(int from,int tp,int spend){

++tot;nxt[tot]=head[from];head[from]=tot;to[tot]=tp;wei[tot]=1;cost[tot]=spend;
++tot;nxt[tot]=head[tp];head[tp]=tot;to[tot]=from;wei[tot]=0;cost[tot]=-spend;

}

bool bfs(){

memset(dis,0x3f,sizeof dis);
memset(vis,false,sizeof vis);
dis[145] = 0;
que.push(145);
int now;

do{

now = que.front();
vis[now] = false;
que.pop();

for(int i=head[now];i;i=nxt[i])
if(dis[to[i]]>dis[now]+cost[i] && wei[i]){
dis[to[i]] = dis[now]+cost[i];
pre[to[i]] = now;
pres[to[i]] = i;
if(!vis[to[i]]){
que.push(to[i]);
vis[to[i]] = true;
}
}

}while(!que.empty());

return dis[146]!=inf;

}

void dinic(){

int now = 146;
used += dis[146];

while(now != 145){
--wei[pres[now]];
++wei[pres[now]^1];
now = pre[now];
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息