• 洛谷P2762 太空飞行计划问题(最小割)


    传送门

    我们可以把实验放在左边,仪器放在右边,点有点权,然后连对应的有向边,就是求一个最大权闭合图,可以转化为最小割来做(关于这具体是个啥……可以百度胡伯涛《最小割模型在信息学竞赛中的应用》)

    总而言之,就是求一个图,每一个点有点权,闭合图就是若图中有点$u$,且原图中存在边$(u,v)$,那么点$v$也在图中。然后求一个最大权的闭合图即可(具体证明看上面)。最大权闭合图可以转化成下面那样建图之后求最小割

    源点向所有实验连边,容量为收益,实验向对应仪器连边,容量为$inf$,仪器向汇点连边,容量为花费,求一个最小割就好了,然后答案就是收益总和减去最小割

    然后考虑怎么求方案,因为最后一次bfs没有增广成功,而与源点想通的点就是闭合图中的点,所以只要最后一次分层图中$dep$不等于$-1$的点即可

     1 //minamoto
     2 #include<cstdio>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<queue>
     6 #define inf 0x3f3f3f3f
     7 using namespace std;
     8 inline bool read(int &res){
     9     res=0;char ch=getchar();
    10     while(!isdigit(ch)){if(ch=='
    ') return false;ch=getchar();}
    11     while(isdigit(ch)){res=res*10+ch-'0',ch=getchar();}
    12     return ch!='
    ';
    13 }
    14 const int N=105,M=10005;
    15 int ver[M],Next[M],head[N],edge[M],cur[N],tot=1;
    16 int dep[N],n,m,s,t,ans;
    17 queue<int> q;
    18 inline void add(int u,int v,int e){
    19     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
    20     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;
    21 }
    22 bool bfs(){
    23     memset(dep,-1,sizeof(dep));
    24     for(int i=0;i<=n+m+1;++i) cur[i]=head[i];
    25     q.push(s),dep[s]=0;
    26     while(!q.empty()){
    27         int u=q.front();q.pop();
    28         for(int i=head[u];i;i=Next[i]){
    29             int v=ver[i];
    30             if(dep[v]<0&&edge[i])
    31             dep[v]=dep[u]+1,q.push(v);
    32         }
    33     }
    34     return ~dep[t];
    35 }
    36 int dfs(int u,int limit){
    37     if(!limit||u==t) return limit;
    38     int flow=0,f;
    39     for(int i=cur[u];i;i=Next[i]){
    40         int v=ver[i];cur[u]=i;
    41         if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){
    42             flow+=f,limit-=f;
    43             edge[i]-=f,edge[i^1]+=f;
    44             if(!limit) break;
    45         }
    46     }
    47     return flow;
    48 }
    49 int dinic(){
    50     int flow=0;
    51     while(bfs()) flow+=dfs(s,inf);
    52     return flow;
    53 }
    54 int main(){
    55     scanf("%d%d",&m,&n);
    56     s=0,t=n+m+1;
    57     for(int i=1,x;i<=m;++i){
    58         scanf("%d",&x),ans+=x;
    59         add(s,i,x);
    60         while(read(x)) add(i,x+m,inf);
    61         add(i,x+m,inf);
    62     }
    63     for(int i=m+1,x;i<=n+m;++i){
    64         scanf("%d",&x);
    65         add(i,t,x);
    66     }
    67     ans-=dinic();
    68     for(int i=1;i<=m;++i)
    69     if(~dep[i]) printf("%d ",i);
    70     putchar(10);
    71     for(int i=m+1;i<=n+m;++i)
    72     if(~dep[i]) printf("%d ",i-m);
    73     putchar(10);
    74     printf("%d
    ",ans);
    75     return 0;
    76 }
  • 相关阅读:
    Infosec institute n00bs CTF writeup
    CTF学习之CODE
    ThinkPHP函数详解:C方法
    流程控制的替代语法
    Jquery DOM
    YII2 请求(request)
    YII2 运行概述(Overview)
    YII2 小部件(widgets)
    YII2 过滤器 filters
    YII2 随笔 视图最佳实践
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9502032.html
Copyright © 2020-2023  润新知