太空飞行计划问题 |
||
|
||
description |
||
W教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
|
||
input |
||
多组数据输入.
每组输入第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接下来是该实验需要的仪器数;接着是对应仪器的编号。最后一行的n个数是配置每个仪器的费用。
|
||
output |
||
每组输出最佳实验方案的净收益
|
||
sample_input |
||
2 3
10 2 1 2
25 2 2 3
5 6 7
|
||
sample_output |
||
17
|
分析(引用 BYvoid大牛的分析):
最大权闭合图问题,可以转化成最小割问题,进而用最大流解决。
建模方法:
把每个实验看作二分图 X集合中的顶点,每个设备看作二分图Y集合中的顶点,增加源 S和汇 T。
1、从 S向每个 Xi连接一条容量为该点收入的有向边。
2、从 Yi向 T 连接一条容量为该点支出的有向边。
3、如果一个实验 i需要设备 j,连接一条从 Xi到 Yj容量为无穷大的有向边。
统计出所有实验的收入只和 Total,求网络最大流 Maxflow,最大收益就是 Total-Maxflow。对应的解就是最小割划分出的
S集合中的点,也就是最后一次增广找到阻塞流时能从 S访问到的顶点。
建模分析:
定义一个割划分出的 S集合为一个解,那么割集的容量之和就是(未被选的 A集合中的顶点的权值 + 被选的B 集合中的顶点
的权值),记为 Cut。A集合中所有顶点的权值之和记为Total,那么Total - Cut 就是(被选的 A集合中的顶点的权值 - 被选
的 B集合中的顶点的权值),即为我们的目标函数,记为 A。要想最大化目标函数 A,就要尽可能使 Cut小,Total 是固定值,所
以目标函数 A 取得最大值的时候,Cut最小,即为最小割。
------------------------------------------------------------------------------------------------------------------------------------------
以上内容没看懂............
#include <iostream> #include <cstdio> using namespace std; const int OO=1e9; const int maxn=1111; const int maxm=111111; struct EDGE{ int to; int flow; int next; }edges[maxm]; int node,edge,src,dest; int head[maxn],dis[maxn],work[maxn],q[maxn]; void prepare(int _node,int _src,int _dest); void addedge(int u,int v,int c); int Dinic_flow(); bool Dinic_bfs(); int Dinic_dfs(int u,int exp); void prepare(int _node,int _src,int _dest) { node=_node; src=_src; dest=_dest; for (int i=0;i<node;i++) head[i]=-1; edge=0; } void addedge(int u,int v,int c) { edges[edge].flow=c;edges[edge].to=v;edges[edge].next=head[u];head[u]=edge++; edges[edge].flow=0;edges[edge].to=u;edges[edge].next=head[v];head[v]=edge++; } int Dinic_flow() { int ret=0,tmp; while (Dinic_bfs()) { for (int i=0;i<node;i++) work[i]=head[i]; while (tmp=Dinic_dfs(src,OO)) ret+=tmp; } return ret; } bool Dinic_bfs() { int u,v,r=0; for (int i=0;i<node;i++) dis[i]=-1; q[r++]=src; dis[src]=0; for (int l=0;l<r;l++) { u=q[l]; for (int i=head[u];i!=-1;i=edges[i].next) { v=edges[i].to; if (edges[i].flow&&dis[v]<0) { q[r++]=v; dis[v]=dis[u]+1; if (v==dest) return true; } } } return false; } int Dinic_dfs(int u,int exp) { int v,tmp; if (u==dest) return exp; for (int &i=work[u];i!=-1;i=edges[i].next) { v=edges[i].to; if (edges[i].flow&&dis[v]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,edges[i].flow)))>0) { edges[i].flow-=tmp; edges[i^1].flow+=tmp; return tmp; } } return 0; } int main() { int n,m,total,maxflow; while (scanf("%d%d",&m,&n)!=EOF) { prepare(m+n+2,0,m+n+1); total=0; for (int i=1;i<=m;i++) { int t,k,v; scanf("%d%d",&t,&k); addedge(src,i,t); total+=t; while (k--) { scanf("%d",&v); addedge(i,m+v,OO); } } for (int i=m+1;i<=m+n;i++) { int t; scanf("%d",&t); addedge(i,dest,t); } //cerr<<"read-over"<<endl; maxflow=Dinic_flow(); //cerr<<"maxflow---"<<maxflow<<endl; printf("%d\n",total-maxflow); } return 0; }