• 太空飞行计划问题


    题目描述

    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=='
    ') 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 }
  • 相关阅读:
    使用类的静态字段和构造函数,我们可以跟踪某个类所创建对象的个数。请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?”。
    《大道至简》第三章读后感
    动手动脑
    zencart设置特价商品价格
    如何设置zencart买满多少免运费?
    zencart分类页每页显示产品数量自定义选择的方法
    Access数据库LIKE问题
    zencart清空产品商品实用命令
    dedecms织梦后台发布文章提示“标题不能为空”的解决办法
    zencart重置用户登录密码sql
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7755485.html
Copyright © 2020-2023  润新知