• 网络流24题——太空飞行计划问题(最大权闭合图)


    链接:https://www.oj.swust.edu.cn/oj/problem/show/1737

    分析:把实验和仪器都看做点,点权为盈利(仪器的盈利为负),从实验到所需仪器连一条边,求图的最大权闭合图。

    最大权闭合图求法:增加源汇点s、t,对于每个点,设权重为w,若w>0,从s向该点连一条边,容量为w,若w<0,从该点向t连一条边,容量为-w,再把原有的边全部容量改为无穷大,求一下该图的最小割即为最大权,割完和s所在集合就是最大权闭合图,也就是需要做的实验和需要的仪器。

      1 #include<iostream>
      2 #include<vector>
      3 #include<queue>
      4 #include<stack>
      5 #include<cstdio>
      6 #include<cstring>
      7 using namespace std;
      8 const int maxn=1e3+5,INF=1e9;
      9 int m,n;
     10 struct Edge{
     11     int from,to,cap,flow;
     12     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
     13 };
     14 struct ISAP{
     15     int n,s,t;
     16     vector<Edge> edges;
     17     vector<int> G[maxn];
     18     bool vis[maxn];
     19     int d[maxn];
     20     int cur[maxn];
     21     int p[maxn];
     22     int num[maxn];
     23 
     24     void init(int n){
     25         this->n=n;
     26         edges.clear();
     27         for(int i=0;i<n;i++)G[i].clear();
     28     }
     29 
     30     void AddEdge(int from,int to,int cap){
     31         edges.push_back(Edge(from,to,cap,0));
     32         edges.push_back(Edge(to,from,0,0));
     33         G[from].push_back(edges.size()-2);
     34         G[to].push_back(edges.size()-1);
     35     }
     36 
     37     void BFS(){
     38         memset(vis,0,sizeof(vis));
     39         queue<int> Q;
     40         Q.push(t);
     41         d[t]=0;
     42         vis[t]=1;
     43         while(!Q.empty()){
     44             int x=Q.front();Q.pop();
     45             for(int i=0;i<G[x].size();i++){
     46                 Edge &e=edges[G[x][i]^1];
     47                 if(e.flow==e.cap)continue;
     48                 if(!vis[e.from]){
     49                     vis[e.from]=1;
     50                     d[e.from]=d[x]+1;
     51                     Q.push(e.from);
     52                 }
     53             }
     54         }
     55     }
     56 
     57     int Augment(){
     58         int x=t,a=INF;
     59         while(x!=s){
     60             Edge &e=edges[p[x]];
     61             a=min(a,e.cap-e.flow);
     62             x=edges[p[x]].from;
     63         }
     64         x=t;
     65         while(x!=s){
     66             edges[p[x]].flow+=a;
     67             edges[p[x]^1].flow-=a;
     68             x=edges[p[x]].from;
     69         }
     70         return a;
     71     }
     72 
     73     int Maxflow(int s,int t){
     74         this->s=s;this->t=t;
     75         int flow=0;
     76         BFS();
     77         memset(num,0,sizeof(num));
     78         for(int i=0;i<n;i++)num[d[i]]++;
     79         int x=s;
     80         memset(cur,0,sizeof(cur));
     81         while(d[s]<n){
     82             if(x==t){
     83                 flow+=Augment();
     84                 x=s;
     85             }
     86             int ok=0;
     87             for(int i=cur[x];i<G[x].size();i++){
     88                 Edge &e=edges[G[x][i]];
     89                 if(e.cap>e.flow&&d[x]==d[e.to]+1){
     90                     ok=1;
     91                     p[e.to]=G[x][i];
     92                     cur[x]=i;
     93                     x=e.to;
     94                     break;
     95                 }
     96             }
     97             if(!ok){
     98                 int m=n-1;
     99                 for(int i=0;i<G[x].size();i++){
    100                     Edge &e=edges[G[x][i]];
    101                     if(e.cap>e.flow)m=min(m,d[e.to]);
    102                 }
    103                 if(--num[d[x]]==0)break;
    104                 num[d[x]=m+1]++;
    105                 cur[x]=0;
    106                 if(x!=s)x=edges[p[x]].from;
    107             }
    108         }
    109         return flow;
    110     }
    111 }isap;
    112 
    113 int main(){
    114 //    freopen("e:\in.txt","r",stdin);
    115     scanf("%d%d",&m,&n);
    116     char c;
    117     int v,ans=0;
    118     isap.init(n+m+2);
    119     for(int i=n+1;i<=n+m;i++){
    120         scanf("%d",&v);
    121         ans+=v;
    122         isap.AddEdge(0,i,v);
    123         c=getchar();
    124         while(c==' '){
    125             scanf("%d",&v);
    126             c=getchar();
    127             isap.AddEdge(i,v,INF);
    128         }
    129     }
    130     for(int i=1;i<=n;i++){
    131         scanf("%d",&v);
    132         isap.AddEdge(i,n+m+1,v);
    133     }
    134     ans-=isap.Maxflow(0,n+m+1);
    135     isap.BFS();
    136     for(int i=n+1;i<=n+m;i++){
    137         if(!isap.vis[i]){
    138             printf("%d ",i-n);
    139         }
    140     }
    141 
    142     printf("
    ");
    143     for(int i=1;i<=n;i++){
    144         if(!isap.vis[i]){
    145             printf("%d ",i);
    146         }
    147     }
    148     printf("
    ");
    149     printf("%d
    ",ans);
    150     return 0;
    151 }
  • 相关阅读:
    Day 13 匿名函数 :内置函数: 闭包
    Day 12 生成器:生成器表达式:列表表达式:yield:yield from:内置函数
    最近这些天
    正则表达式 I
    Python 软件规范开发
    模块
    常用模块介绍 time datetime os sys hashlib json pickle collections
    模拟博客园登录 基础版
    SQL 必知必会
    Python中的线程和进程
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7448053.html
Copyright © 2020-2023  润新知