zoukankan      html  css  js  c++  java
  • 【题解】太空飞行计划问题

    太空飞行计划问题

    还是利用最小割的性质,这种题目叫做最大权闭合子图。

    建模方法是这样

    img

    直接跑最小割,用奖金减去最小割就是答案。方案就是最后一遍bfs能遍历的点

    考虑最小割的意义,就是把边删掉使得(S,T)不连通。

    同样地,由于我们无法改变仪器和任务依赖的关系,只能改变一个点是否选择这个状态,所以我们让实验和仪器的连边为(inf)表示我们无法更改这个关系。

    我们考虑鸽掉的奖金边是什么意思:这条奖金边是一次流的限制关系,是劣势的一方

    考虑割掉的仪器边是什么意思:这条仪器边太小了,以至于实验赚的流随便流满了。

    考虑总奖金减去最小割代价是什么,就是

    [sum ext{奖金}-sum ext{不要的奖金}-sum ext{不买的仪器} ]

    实际上,我们可以考虑每一条流的流经路线,也能获得同样的理解。

    其他题我能够独立完成,这道题不得不看题解...实在是我思维强度不够

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    
    using namespace std;  typedef long long ll;
    int qaq,n;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57) f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    
    inline int sp(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57) f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          if(c=='
    ') f=1;
          return f?-ret:ret;
    }
    const int maxn=1e2+5;
    struct E{
          int to,nx,w;
          E(){to=nx=w=0;}
          E(const int&a,const int&b,const int&c){to=a;nx=b;w=c;}
    }e[maxn<<4];
    int head[maxn];
    int cnt=1;
    const int inf=0x3f3f3f3f;
    int S,T,m;
    inline void add(const int&fr,const int&to,const int&w,const int&f){
          //printf("fr=%d to=%d w=%d cnt=%d
    ",fr,to,w,cnt);
          e[++cnt]=E(to,head[fr],w);
          head[fr]=cnt;
          if(f) add(to,fr,0,0);
    }
    
    int sum=0;
    queue < int > q;
    int d[maxn],cur[maxn];
    inline bool bfs(){
          for(register int t=1;t<=m+n+2;++t) d[t]=0,cur[t]=head[t];
          d[S]=1;q.push(S);
          while(q.size()){
    	    register int now=q.front();
    	    q.pop();
    	    for(register int t=head[now];t;t=e[t].nx){
    		  if(e[t].w>0&&d[e[t].to]==0){
    			d[e[t].to]=d[now]+1;
    			q.push(e[t].to);		
    		  }
    	    }
          }
          return d[T];
    
    }
    
    int dfs(const int&now,int fl){
          if(now==T||fl==0)return fl;
          register int ret=0;
          for(register int&t=cur[now];t;t=e[t].nx){
    	    if(e[t].w>0&&d[e[t].to]==d[now]+1){
    		  int d=dfs(e[t].to,min(e[t].w,fl));
    		  e[t].w-=d;e[t^1].w+=d;ret+=d;fl-=d;
    	    }
          }
          return ret;
    }
    
    
    inline int dinic(){
          int ret=0;
          while(bfs())ret+=dfs(S,inf);
          return ret;
    }
    
    
    int main(){
    #ifndef ONLINE_JUDGE
          //freopen("in.in","r",stdin);
          //freopen("out.out","w",stdout);
    #endif
          n=qr();m=qr();
          S=1;T=n+m+2;
          for(register int t=1;t<=n;++t){
    	    int t1=qr();
    	    add(S,t+1,t1,1);
    	    sum+=t1;
    	    while(1){
    		  t1=sp();
    		  //cout<<t<<' '<<t1<<endl;
    		  add(t+1,abs(t1)+n+1,inf,1);
    		  if(t1<0)break;
    	    }
          }
          for(register int t=1;t<=m;++t) add(t+n+1,T,qr(),1);
          int ans=sum-dinic();
          for(register int t=head[S];t;t=e[t].nx)
    	    if(d[e[t].to]) printf("%d ",e[t].to-1);
          putchar('
    ');
          for(register int t=head[T];t;t=e[t].nx)
    	    if(d[e[t].to]) printf("%d ",e[t].to-n-1);
          printf("
    %d
    ",ans);
          return 0;
    }
    
    
  • 相关阅读:
    数据结构_线性结构
    多线程01_基础
    操作系统05_文件管理
    解析静态内部类的使用目的与限制(转)
    mysql去除重复记录案例
    mysql 索引使用策略及优化
    mysql 索引数据结构及原理
    mysql 索引的简单使用
    当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法
    14 线程间协作的两种方式:wait、notify、notifyAll和Condition
  • 原文地址:https://www.cnblogs.com/winlere/p/11234631.html
Copyright © 2011-2022 走看看