zoukankan      html  css  js  c++  java
  • [网络流24题]太空飞行计划问题

    题目描述

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

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

    题解

    同样需要Ford-Fulkerson定理

    源点向实验连容量为奖金的钱,实验向仪器连容量无限的边,仪器向汇点连容量为花费的边

    答案同样是总奖金-最小割

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define INF 0x3f3f3f3f
      6 using namespace std;
      7 int n,m,cnt,tot,tmp;
      8 int st,ed,ans,tp1,tp2;
      9 char usd;
     10 int stmt[205];
     11 bool used[205];
     12 int inst[205];
     13 bool vis[205];
     14 int cst[205];
     15 int pay[205];
     16 int dis[205];
     17 int head[205];
     18 struct Edge{
     19     int fr;
     20     int to;
     21     int flw;
     22     int nxt;
     23 }edge[10005],pth[10005];
     24 void init(){
     25     memset(head,-1,sizeof(head));
     26 }
     27 void addedge(int u,int v,int f){
     28     edge[cnt].fr=u;
     29     edge[cnt].to=v;
     30     edge[cnt].flw=f;
     31     edge[cnt].nxt=head[u];
     32     head[u]=cnt++;
     33     edge[cnt].fr=v;
     34     edge[cnt].to=u;
     35     edge[cnt].nxt=head[v];
     36     head[v]=cnt++;
     37 }
     38 int bfs(int ban){
     39     queue<int>que;
     40     memset(dis,0x3f,sizeof(dis));
     41     que.push(st);dis[st]=0;
     42     while(!que.empty()){
     43         int u=que.front();
     44         que.pop();
     45         for(int i=head[u];i!=-1;i=edge[i].nxt){
     46             int v=edge[i].to;
     47             if(!edge[i].flw||v==ban)continue;
     48             if(dis[v]==0x3f3f3f3f){
     49                 dis[v]=dis[u]+1;
     50                 que.push(v);
     51             }
     52         }
     53     }
     54     return (dis[ed]!=0x3f3f3f3f);
     55 }
     56 int dfs(int u,int flw,int ban){
     57     if(u==ed)return flw;
     58     int All=0;int f;
     59     for(int i=head[u];i!=-1;i=edge[i].nxt){
     60         int v=edge[i].to;
     61         if(dis[v]!=dis[u]+1)continue;
     62         if((f=dfs(v,min(flw,edge[i].flw),ban))>0){
     63             edge[i].flw-=f;
     64             edge[i^1].flw+=f;
     65             flw-=f;All+=f;
     66             if(!flw)break;
     67         }
     68     }
     69     return All;
     70 }
     71 void dinic(int ban){
     72     tmp=0;
     73     memcpy(edge,pth,sizeof(edge));
     74     while(bfs(ban)){
     75         tmp+=dfs(st,INF,ban);
     76     }
     77 }
     78 int main(){
     79     init();
     80     scanf("%d%d",&m,&n);ed=n+m+1;
     81     for(int i=1;i<=m;i++){
     82         scanf("%d",&pay[i]);tot+=pay[i];
     83         usd=getchar();int tl=0;
     84         while(usd!='
    '&&usd!='
    '){
     85             if(usd==' '&&tl){
     86                 addedge(i,tl+m,INF);
     87                 tl=0;usd=getchar();
     88                 continue;
     89             }
     90             if(usd>='0')tl=tl*10+usd-'0';
     91             usd=getchar();
     92         }
     93         if(tl)addedge(i,tl+m,INF);
     94         addedge(st,i,pay[i]);
     95     }
     96     for(int i=1;i<=n;i++){
     97         scanf("%d",&cst[i]);
     98         addedge(i+m,ed,cst[i]);
     99     }
    100     memcpy(pth,edge,sizeof(pth));
    101     dinic(-1);ans=tmp;
    102     for(int i=1;i<=n;i++){
    103         dinic(i+m);
    104         if(tmp+cst[i]==ans){
    105             inst[++tp1]=i;
    106             used[i]=true;
    107         }
    108     }
    109     for(int i=1;i<=m;i++){
    110         int fl=0;
    111         for(int j=head[i];j!=-1;j=edge[j].nxt){
    112             int v=edge[j].to;
    113             if(!v)continue;
    114             if(!used[v-m]){
    115                 fl=1;
    116                 break;
    117             }
    118         }
    119         if(!fl)stmt[++tp2]=i;
    120     }
    121     sort(stmt+1,stmt+tp2+1);
    122     sort(inst+1,inst+tp1+1);
    123     for(int i=1;i<=tp2;i++){
    124         printf("%d",stmt[i]);
    125         if(i!=tp2)printf(" ");
    126     }printf("
    ");
    127     for(int i=1;i<=tp1;i++){
    128         printf("%d",inst[i]);
    129         if(i!=tp1)printf(" ");
    130     }printf("
    ");ans=tot-ans;
    131     printf("%d
    ",ans);
    132     return 0;
    133 }
  • 相关阅读:
    openstack newton 版本 horizon二次开发
    ubuntu 远程root登录
    记录一次用户态踩内存问题
    (leetcode)二叉树的前序遍历-c语言实现
    通过blacklist来禁用驱动
    最小栈问题
    判断是否为环形链表
    按照层次序列创建二叉树,并判断二叉树是否为二叉搜索树
    操作系统交付时需要做哪些安全检查项
    RDMA相关的技术网站
  • 原文地址:https://www.cnblogs.com/lnxcj/p/10130977.html
Copyright © 2011-2022 走看看