太空飞行计划问题

题目描述

W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E= {E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjÍI。配置仪器 Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而 配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。

对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。

输入输出格式

输入格式:

第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。

输出格式:

一行是净收益。

输入输出样例

输入样例#1: 复制
2 3
10 1 2
25 2 3
5 6 7
输出样例#1: 复制
最大权闭合回路
将每一个实验与S连边,流量为收益
将器材与T连边,流量为花费
将实验与需要器材连inf的边
于是可以求最小割
此时会割掉一些与T相连和与S相连的边,但能保证S和T不连通
这样,你选了一个实验,就必须割掉对应器材与T的边
对于器材,割掉相当于选择
对于实验,割掉相当于不选
于是显然答案就是实验利益和-最小割=利益和-最大流
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 struct Node
  8 {
  9   int next,to,c;
 10 }edge[200001],edge2[200001];
 11 int num=1,head[1001],cur[1001],n,m,dist[1001],ans,sum,maxflow,Max;
 12 void add(int u,int v,int c)
 13 {
 14   num++;
 15   edge[num].next=head[u];
 16   head[u]=num;
 17   edge[num].to=v;
 18   edge[num].c=c;
 19 }
 20 bool get(int i)
 21 {
 22   char ch=getchar();
 23   while (ch==' ') ch=getchar();
 24   int x=0;
 25   while (ch>='0'&&ch<='9') 
 26     {
 27       x=x*10+ch-'0';
 28       ch=getchar();
 29     }
 30   add(i,m+x,2e9);
 31   add(m+x,i,0);
 32   if (ch=='\n') return 0;
 33   return 1;
 34 }
 35 bool bfs(int S,int T)
 36 {int i;
 37   memset(dist,-1,sizeof(dist));
 38   queue<int>Q;
 39   Q.push(S);
 40   dist[S]=1;
 41   while (!Q.empty())
 42     {
 43       int u=Q.front();
 44       Q.pop();
 45       for (i=head[u];i;i=edge[i].next)
 46     {
 47       int v=edge[i].to;
 48       if (edge[i].c>0&&dist[v]==-1)
 49         {
 50           dist[v]=dist[u]+1;
 51           Q.push(v);
 52         }
 53     }
 54     }
 55   if (dist[T]==-1) return 0;
 56   return 1;
 57 }
 58 int dfs(int x,int flow,int des)
 59 {
 60   int res=0;
 61   if (x==des) return flow;
 62   for (int &i=cur[x];i;i=edge[i].next)
 63   {
 64       int v=edge[i].to;
 65       if (dist[v]==dist[x]+1&&edge[i].c)
 66     {
 67       int tmp=dfs(v,min(flow-res,edge[i].c),des);
 68           if (tmp<0) continue;
 69           edge[i].c-=tmp;
 70           edge[i^1].c+=tmp;
 71           res+=tmp;
 72           if (res==flow) return res;
 73     }
 74   }
 75   return res;
 76 }
 77 void Dinic(int S,int T)
 78 {
 79   maxflow=0;
 80   while (bfs(S,T))
 81     {
 82       memcpy(cur,head,sizeof(cur));
 83       int a=0;
 84       while (a=dfs(S,2e9,T)) maxflow+=a;
 85     }
 86   return;
 87 }
 88 int main()
 89 {int i,val,S,T,j;
 90   cin>>m>>n;
 91   for (i=1;i<=m;i++)
 92     {
 93       scanf("%d",&val);
 94       sum+=val;
 95       add(0,i,val);
 96       add(i,0,0);
 97       while (get(i));
 98     }
 99   for (i=1;i<=n;i++)
100     {
101       scanf("%d",&val);
102       add(m+i,m+n+1,val);
103       add(m+n+1,m+i,0);
104     }
105   S=0;T=m+n+1;
106   memcpy(edge2,edge,sizeof(edge2));
107   Dinic(S,T);
108   ans=maxflow;
109   ans=sum-ans;
110   cout<<ans;
111 }

 

posted @ 2017-10-30 17:30  Z-Y-Y-S  阅读(283)  评论(0编辑  收藏  举报