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

这道题写了好久啊!
先说一下建图过程吧:
把每个仪器看作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.
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值