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

    题意

    有m个实验,n个器材,每个实验做完会得到一些钱,每个实验需要一些器械才能完成,买器材会花钱,器材可以一起用,求最大利益。

    n,m<=50

    题解

    直接写做法了,没做过就想不出来。

    源点向实验连边,流量为实验所得的钱,器材想汇点连边,流量为器材花费,实验与相应的器材连边,流量inf。

    先假设没花钱做了所有实验得到了所有钱ans(不要face)。

    求一遍最小割即可,ans-最小割就是答案。

    割掉实验的连边就是不做这个实验,割掉器材的连边就是买这个器材。

    输出方案就输出与s连通的即可。(为啥我也不知道)

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=105;
    const int maxm=2705;
    const int inf=1000005;
    int n,m,s,t,ans;
    int val[maxn];
    bool flag,get[maxn];
    int cnt=1,head[maxn];
    struct edge{
      int x,y,next,val;
    }e[maxm<<1];
    
    void add(int x,int y,int val){
      e[++cnt]=(edge) {x,y,head[x],val};
      head[x]=cnt;
    }
    
    template<class T>inline void read(T &x){
      x=0;char ch=getchar();
      while(!isdigit(ch)) ch=getchar();
      while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
      flag|=(ch=='
    ');
    }
    
    int d[maxn];
    
    bool bfs(){
      queue<int> q;
      memset(d,0,sizeof(d));
      q.push(s);d[s]=1;
      while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=head[x];i;i=e[i].next){
          int y=e[i].y;
          if(e[i].val&&!d[y]){
            d[y]=d[x]+1;
            if(y==t) return true;
            q.push(y);
          }
        }
      }
      return false;
    }
    
    int dfs(int x,int flow){
      if(x==t) return flow;
      int rest=flow,k;
      for(int i=head[x];i;i=e[i].next){
        int y=e[i].y;
        if(e[i].val&&d[y]==d[x]+1){
          k=dfs(y,min(rest,e[i].val));
          if(!k) d[y]=0;
          e[i].val-=k;
          e[i^1].val+=k;
          rest-=k;
        }
      }
      return flow-rest;
    }
    
    int dinic(){
      int res=0;
      while(bfs()) res+=dfs(s,0x3f3f3f);
      return res;
    }
    
    int main(){
      read(m);read(n);
      s=0;t=n+m+1;
      for(int i=1;i<=m;i++){
        int x;read(x);
        ans+=x;
        add(s,i,x);
        add(i,s,0);
        flag=false;
        while(!flag){
          read(x);
          add(i,x+m,inf);
          add(x+m,i,0);
        }
      }
      for(int i=1;i<=n;i++){
        int x;read(x);
        add(i+m,t,x);
        add(t,i+m,0);
      }
      ans-=dinic();
      for(int i=1;i<=m;i++) if(d[i]) printf("%d ",i);
      putchar(10);
      for(int i=m+1;i<=n+m;i++) if(d[i]) printf("%d ",i-m);
      putchar(10);
      printf("%d",ans);
    }
    View Code
  • 相关阅读:
    如何学习区块链
    用Python从零开始创建区块链
    区块链入门
    什么是区块链
    localStorage使用总结
    整理vue学习笔记
    SCSS 教程
    vue — 创建vue项目
    软件开发的常见文档
    史上最全的CSS hack方式一览(转)
  • 原文地址:https://www.cnblogs.com/sto324/p/11334074.html
Copyright © 2011-2022 走看看