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

网络流24题 -No.18 分配问题

2015-06-11 19:01 615 查看
问题描述
有 n件工作要分配给 n个人做。第 i 个人做第 j 件工作产生的效益为c[i,j] 。试设计一个将n 件工作分配给 n个人做的分配方案,使产生的总效益最大。

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

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

结果输出
程序运行结束时,输出最小总效益和最大总效益。

输入文件示例

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

把所有人看做二分图中顶点Xi,所有工作看做二分图中顶点Yi,建立附加源S汇T。
1、从S向每个Xi连一条容量为1,费用为0的有向边。
2、从每个Yi向T连一条容量为1,费用为0的有向边。
3、从每个Xi向每个Yj连接一条容量为无穷大,费用为Cij的有向边。

求最小费用最大流,最小费用流值就是最少运费,求最大费用最大流,最大费用流值就是最多运费。

具体实现方法见《网络流24题 -No.17 运输问题》

代码:

const
maxn=100000000;

var
ot,ot1,ne1,cap1,ne,cap,h:array[0..30000]of longint;
cost,cost1:array[0..30000,1..2]of longint;
g,g1,pre,dis:array[0..1010]of longint;
inq:array[0..1010]of boolean;
e,s,t,c,i,n,m,ans,j:longint;

procedure addedge(x,y,z,w:longint);
begin
ot[e]:=y; ne[e]:=g[x]; cap[e]:=z; cost[e,1]:=w; cost[e,2]:=-w; g[x]:=e; inc(e);
ot[e]:=x; ne[e]:=g[y]; cap[e]:=0; cost[e,1]:=-w; cost[e,2]:=w; g[y]:=e; inc(e);
end;

function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;

function spfa(c:longint):boolean;
var
x,y,l,r,p:longint;
begin
for i:=s to t do
begin dis[i]:=maxn; inq[i]:=false; end;
l:=0; r:=1; dis[s]:=0; inq[s]:=true; h[1]:=s; pre[s]:=-1;
while l<r do
begin
inc(l);
x:=h[l];
p:=g[x];
while p>-1 do
begin
y:=ot[p];
if (cap[p]>0)and(dis[y]>dis[x]+cost[p,c])
then begin
dis[y]:=dis[x]+cost[p,c]; pre[y]:=p;
if inq[y]=false
then begin inq[y]:=true; inc(r); h[r]:=y; end;
end;
p:=ne[p];
end;
inq[x]:=false;
end;
exit(dis[t]<>maxn);
end;

function find_path(c:longint):longint;
var
x,p,tmp,path:longint;
begin
x:=t; path:=maxn; tmp:=0;
while x>s do
begin
p:=pre[x];
path:=min(path,cap[p]);
x:=ot[p xor 1];
end;
x:=t;
while x>s do
begin
p:=pre[x];
inc(tmp,path*cost[p,c]);
inc(cap[p xor 1],path);
dec(cap[p],path);
x:=ot[p xor 1];
end;
exit(tmp);
end;

begin
e:=0;
fillchar(g,sizeof(g),255);
readln(n);
s:=0; t:=2*n+1; ans:=0;
for i:=1 to n do
begin addedge(s,i,1,0); addedge(n+i,t,1,0); end;
for i:=1 to n do
for j:=1 to n do
begin
read(c);
addedge(i,n+j,maxn,c);
end;
g1:=g; ot1:=ot; cap1:=cap; ne1:=ne; cost1:=cost;
while spfa(1) do
inc(ans,find_path(1));
writeln(ans);
ans:=0;
g:=g1; ot:=ot1; cap:=cap1; ne:=ne1; cost:=cost1;
while spfa(2) do
inc(ans,find_path(2));
writeln(-ans);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: