太空飞行计划问题 2011-12-29

算法实现题8-2 太空飞行计划问题(习题 8-11)
´问题描述:
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业
性实验而获取利润。现已确定了一个可供选择的实验集合 E={E1,E2,…,Em},和进行这
些实验需要使用的全部仪器的集合I={I1, I2,…In}。 实验 Ej需要用到的仪器是 I的子集 RjÍI。
配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的
任务是找出一个有效算法, 确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才
能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部
费用的差额。
´编程任务:
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
´数据输入:
由文件input.txt提供输入数据。文件第 1行有 2 个正整数 m和 n。m是实验数,n是仪
器数。接下来的 m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费
用;接着是该实验需要用到的若干仪器的编号。最后一行的 n个数是配置每个仪器的费用。 
´结果输出:
程序运行结束时,将最佳实验方案输出到文件 output.txt 中。第 1 行是实验编号;第 2
行是仪器编号;最后一行是净收益。 
 输入文件示例
input.txt
2 3
10 1 2
25 2 3
5 6 7

 

输出文件示例
output.txt
1 2 
1 2 3 
17

 

___________________________

最小割。

把每个实验看作二分图X集合中的顶点,每个设备看作二分图Y集合中的顶点,增加源S和汇T。
1、从S向每个Xi连接一条容量为该点收入的有向边。
2、从Yi向T连接一条容量为该点支出的有向边。
3、如果一个实验i需要设备j,连接一条从Xi到Yj容量为无穷大的有向边。

统计出所有实验的收入只和Total,求网络最大流Maxflow,最大收益就是Total-Maxflow。对应的解就是最小割划分出的S集合中的点,也就是最后一次增广找到阻塞流时能从S访问到的顶点。

___________________________

  1 Program Stone;
  2 var s,t,n,m,flow,tot,le:longint;
  3     head,vh,cur,dis:array[0..5000]of longint;
  4     next,point,date:array[-20000..20000]of longint;
  5     cut:array[0..5000]of boolean;
  6  procedure add(x,y,z:longint);
  7   begin
  8     inc(le);
  9     date[le]:=z;
 10     point[le]:=y;
 11     next[le]:=head[x];
 12     head[x]:=le;
 13     point[-le]:=x;
 14     next[-le]:=head[y];
 15     head[y]:=-le;
 16   end;
 17  procedure init;
 18  var i,j,k:longint;
 19   begin
 20     readln(m,n);
 21     s:=0;t:=m+n+1;
 22     for i:=1 to m do
 23      begin
 24       read(k);add(s,i,k);
 25       inc(tot,k);
 26       while not(eoln) do
 27        begin
 28          read(j);
 29          add(i,j+m,maxlongint);
 30        end;
 31      end;
 32     for i:=1 to n do
 33      begin
 34        read(j);
 35        add(i+m,t,j);
 36      end;
 37   end;
 38  function min(a,b:longint):longint;
 39   begin
 40     if a<b then min:=a else min:=b;
 41   end;
 42  function aug(x,nf:longint):longint;
 43  var i,j,l,d,minh,ins:longint;
 44   begin
 45     if x=t then exit(nf);
 46     l:=nf;
 47     i:=cur[x];
 48     while i<>0 do
 49      begin
 50         if (date[i]>0)and(dis[point[i]]+1=dis[x]) then
 51           begin
 52              cur[x]:=i;
 53              d:=aug(point[i],min(l,date[i]));
 54              dec(date[i],d);
 55              inc(date[-i],d);
 56              dec(l,d);
 57              if (l=0)or(dis[s]=t+1) then exit(nf-l);
 58           end;
 59         i:=next[i];
 60      end;
 61     if l=nf then
 62       begin
 63          minh:=t;
 64          i:=head[x];
 65          while i<>0 do
 66           begin
 67             if (date[i]>0)and(dis[point[i]]<minh) then begin minh:=dis[point[i]];ins:=i;end;
 68             i:=next[i]
 69           end;
 70          cur[x]:=ins;
 71          dec(vh[dis[x]]);
 72          if vh[dis[x]]=0 then dis[s]:=t+1;
 73          dis[x]:=minh+1;
 74          inc(vh[dis[x]]);
 75       end;
 76     aug:=nf-l;
 77   end;
 78  procedure dfs(x:longint);
 79  var i:longint;
 80   begin
 81     cut[x]:=true;
 82     i:=head[x];
 83     while i<>0 do
 84      begin
 85        if (date[i]<>0)and(cut[point[i]]=false) then dfs(point[i]);
 86        i:=next[i];
 87      end;
 88   end;
 89  procedure print;
 90  var i,j:longint;
 91   begin
 92     fillchar(cut,sizeof(cut),false);
 93     dfs(s);
 94     for i:=1 to m do
 95      if cut[i]{=false} then write(i,' ');
 96     writeln;
 97     for i:=m+1 to m+n do
 98      if cut[i]{=false} then write(i-m,' ');
 99     writeln;
100     writeln(tot-flow);
101   end;
102 
103  procedure main;
104  var i,j:longint;
105   begin
106     vh[0]:=t+1;
107     for i:=s to t do cur[i]:=head[i];
108     while dis[s]<t+1 do inc(flow,aug(s,maxlongint));
109     print;
110   end;
111 
112 Begin
113  assign(input,'prog82.in');assign(output,'prog82.out');
114  reset(input);rewrite(output);
115    init;
116    main;
117  close(input);close(output);
118 end.
119 
120  

 

posted on 2016-03-02 20:23  Yesphet  阅读(167)  评论(0编辑  收藏  举报