太空飞行计划问题 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