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

[网络流24题 #2]太空飞行计划问题

2014-01-21 13:45 561 查看
这道题写了好久啊!

先说一下建图过程吧:

把每个仪器看作X顶点,把实验看作Y顶点,增加S和T点。

S点连接所有的X顶点,权值为每个仪器的费用,T点连接所有实验,权值是收入。

如果实验需要相应的仪器,则把对应的X,Y顶点相连,权值为无穷大,

那么最大收入则为所有实验的收入减去最小割,根据最小割最大流定理,最小割就是最大流。

对应的解就是最小割划分出的T集合中的点,也就是最后一次寻找增广路径时不能从S访问到的顶点。

好吧,cpp写手残了,用pascal解决了:type
pnode=^tnode;
tnode=record
x:longint;
next:pnode;
end;
var
f,g,c:array[0..200,0..200]of longint;
m,n,i,j,t,sum,flow:longint;
vd,d:array[0..200]of longint;
ii:array[0..200]of boolean;
ee:array[0..200]of pnode;

procedure insert(a,b:longint);
var
p:pnode;
begin
new(p);
p^.x:=b;
p^.next:=ee[a];
ee[a]:=p;
end;

procedure readdata;
begin
readln(m,n);
fillchar(g,sizeof(g),0);
fillchar(f,sizeof(f),0);
fillchar(c,sizeof(c),0);
sum:=0;
for i:=1 to m do
begin
read(t);
inc(sum,t);
inc(c[n+i,n+m+1],t);
inc(g[n+i,n+m+1],t);
while not eoln do
begin
read(t);
insert(i,t);
c[t,i+n]:=maxlongint;
g[t,i+n]:=maxlongint;
end;
end;
for i:=1 to n do
begin
read(t);
inc(g[0,i],t); inc(c[0,i],t);
end;
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
function dfs(u,flow:longint):longint;
var
v,temp:longint;
begin
if u=m+n+1 then exit;
dfs:=0;
for v:=0 to m+n+1 do
if (g[u,v]>0)and(d[u]=d[v]+1) then
begin
temp:=dfs(v,min(flow-dfs,g[u,v]));
dec(g[u,v],temp);
inc(g[v,u],temp);
dfs:=dfs+temp;
if c[u,v]>0 then inc(f[u,v],temp) else dec(f[u,v],temp);
if dfs=flow then exit(dfs);
end;
if d[0]>=m+n+2 then exit;
dec(vd[d[u]]);
if vd[d[u]]=0 then d[0]:=m+n+2;
inc(d[u]);
inc(vd[d[u]]);
end;
procedure choose;//处理方案
begin
{
{debug}
write(d[0],' ');
for i:=m+1 to m+n+1 do write(d[i],' ');
for i:=1 to m do write(d[i],' '); writeln;
for i:=1 to m+n+2 do write(vd[i],' '); writeln;
{debug}
}

for i:=0 to m+n+2 do if vd[i]=0 then break;
//因为汇点为0,所以从0层向上开始找,找到第一个该层没有点的层数,即为断层的地方
for j:=n+1 to n+m do if d[j]<i then write(j-n,' ');
writeln;
for j:=1 to n do if d[j]<i then write(j,' ');
writeln;
//分别找被选中的实验和仪器、如果它所在层小于断层则属于T集、被选中
writeln(sum);
end;
procedure main;
begin
fillchar(vd,sizeof(vd),0);
fillchar(d,sizeof(d),0);
vd[0]:=m+n+2;
while d[0]<m+n+2 do
begin
flow:=dfs(0,maxlongint);
sum:=sum-flow;
end;
choose;
end;
begin
readdata;
main;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络流