zoukankan      html  css  js  c++  java
  • [网络流24题] 太空飞行计划问题 (最大流->最大权闭合图)

    洛谷传送门 LOJ传送门

    做这道题之前建议先看这篇论文,虽然论文里很多地方用了很多术语,但hbt神犇讲得很明白

    这篇题解更加偏向于感性理解

    把问题放到二分图上,左侧一列点是实验,权值为$p[i]$,右侧一列点是仪器,权值为$c[i]$,左侧向右侧连接了许多条出边

    如果想获得$p[i]$,需要保证i的所有出边都被选上了

    按照论文里最大权闭合图的做法,实验和源点$s$相连,流量为$p[i]$,仪器和汇点$t$相连,流量为$c[i]$,实验和仪器之间的边流量为$inf$

    最终的答案就是实验带来的报酬总和-这个图的最大流,即报酬总和去掉 报酬填补费用的总和 ,就是净收益

    我们如何比较感性地理解它呢

    求最大流的过程,可以看成用实验的钱消去仪器的钱的过程

    而有一些实验可能先被遍历到,而这次实验的报酬小于所需仪器的总花费,即这次实验有点亏,但买了给其他实验用的仪器,而其他实验可以把这些钱补回来

    在图上的体现就是,有其他实验的流量沿着反向边流向了这次实验

    通过求最小割,我们把图分割成了两块,一块包含源点,一块包含汇点

    源点指向的每个联通块中,都至少存在一个点,源点向它的流量$>0$,那么这个联通块里的实验仪器组合才是获利的

    那么最终答案就是总获利-最大流,方案就是再进行一次$bfs$,$dep$有值的点,即和源点在同一联通块里的点。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define N1 350
     6 #define M1 3010
     7 #define ll long long
     8 #define dd double
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 
    12 int gint()
    13 {
    14     int ret=0,fh=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    17     return ret*fh;
    18 }
    19 
    20 int n,m,nm,S,T;
    21 int p[N1],c[N1];  
    22 struct Edge{
    23 int head[N1],to[M1<<1],nxt[M1<<1],flow[M1<<1],cte;
    24 void ae(int u,int v,int F)
    25 {
    26     cte++; to[cte]=v; flow[cte]=F;  
    27     nxt[cte]=head[u]; head[u]=cte;
    28 }
    29 }e;
    30 
    31 int que[M1],hd,tl,dep[N1],cur[N1];
    32 int bfs(Edge &E)
    33 {
    34     int x,j,v;
    35     memset(dep,-1,sizeof(dep)); memcpy(cur,E.head,sizeof(cur));
    36     hd=1,tl=0; que[++tl]=S; dep[S]=0; 
    37     while(hd<=tl)
    38     {
    39         x=que[hd++];
    40         for(j=E.head[x];j;j=E.nxt[j])
    41         {
    42             v=E.to[j]; if(dep[v]!=-1||!E.flow[j]) continue;
    43             dep[v]=dep[x]+1; que[++tl]=v;
    44         }
    45     }
    46     return dep[T]!=-1;
    47 }
    48 int dfs(Edge &E,int x,int limit)
    49 {
    50     int j,v,flow,ans=0; if(x==T||!limit) return limit;
    51     for(j=cur[x];j;j=E.nxt[j])
    52     {
    53         cur[x]=j; v=E.to[j];
    54         if( dep[v]==dep[x]+1 && (flow=dfs(E,v,min(E.flow[j],limit))) )
    55         {
    56             limit-=flow; ans+=flow;
    57             E.flow[j]-=flow; E.flow[j^1]+=flow;
    58             if(!limit) break;
    59         }
    60     }
    61     return ans;
    62 }
    63 int use[N1],de;
    64 void Dinic()
    65 {
    66     int mxflow=0,x,j,v,i,flag,sum=0;
    67     for(i=1;i<=m;i++) sum+=p[i];
    68     while(bfs(e)) mxflow+=dfs(e,S,inf);
    69     bfs(e);
    70     for(i=1;i<=m;i++) if(dep[i]!=-1) printf("%d ",i); puts("");
    71     for(i=m+1;i<=m+n;i++) if(dep[i]!=-1) printf("%d ",i-m); puts("");
    72     printf("%d
    ",sum-mxflow);
    73 }
    74 
    75 char str[1000];
    76 int main()
    77 {
    78     scanf("%d%d",&m,&n);
    79     int i,j,x,y,flag,slen; S=m+n+1,T=m+n+2; e.cte=1;
    80     for(i=1,slen=0;i<=m;i++)
    81     {
    82         p[i]=gint(); e.ae(S,i,p[i]), e.ae(i,S,0);
    83         memset(str,0,sizeof(str)); cin.getline(str,1000); slen=0;
    84         while(sscanf(str+slen,"%d",&x)==1)
    85         {
    86             e.ae(i,x+m,inf); e.ae(x+m,i,0); 
    87             if(!x) slen++;
    88             else{ while(x) x/=10,slen++;}
    89             slen++;
    90         }
    91     }
    92     for(i=m+1;i<=m+n;i++) c[i]=gint(), e.ae(i,T,c[i]), e.ae(T,i,0);
    93     Dinic();
    94     return 0;
    95 }
  • 相关阅读:
    Mac OS X:在VirtualBox中使用Xcode连接IPAD
    Xcode:PhoneGap 2.5.0项目创建方法
    Android:网络操作2.3等低版本正常,4.0(ICS)以上出错,换用AsyncTask异步线程get json
    安卓:WebView中iframe,焦点字段出现两个文本输入框,位置错误
    Mac OS X:Mac系统鼠标滚轮方向调整
    Xcode:missing file xxx
    Mac OS X:Xcode常用快捷键
    分形图形神器XaoS
    [转]How to change Atheros AR9285 MAC addr on Win7(Win7下更改Atheros AR9285 MAC地址)
    利用pscp建立“右键发送到”菜单
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10289740.html
Copyright © 2011-2022 走看看