zoukankan      html  css  js  c++  java
  • 「网络流 24 题」太空飞行计划

    OJ题号:
    洛谷2762、LOJ6001、CodeVS1233

    题目大意:
    有$n$个实验和$m$个仪器,每个实验需要依赖若干个仪器,不同实验可以共享一个仪器。
    已知每一个实验$x$,有$p_x$的收益,每一个仪器$y$,有$c_y$的花费。
    求最大净收益。

    思路:
    建立超级源汇$S$和$T$,
    对于每一个实验$x$,连一条从$S$到$x$的容量为$p_x$的边;
    对于每一个实验$x$对应的每一个仪器$y$,连一条从$x$到$y$的容量为$infty$的边;
    对于每一个仪器$y$连一条从$y$到$T$的容量为$c_y$的边。
    这样,如果选择了一个实验,它所依赖的所有仪器都能保证被选中,这样题目就被转化成了一个最大权闭合子图的问题。
    答案即为$displaystyle{sum_{i=1}^{n}}p_i-$最小割。
    对于要输出的方案,可以这样考虑:
    一个实验要是能赚钱,必定不会满流,如果满流则说明实验经费全被仪器消耗掉了;
    同样,最后一次BFS的时候,对于没有满流的实验,其所需仪器也一定不满流;
    最后只要判断Dinic退出时那些实验或仪器是否有被最后最后一次BFS遍历过即可。

    细节:
    1.读入特别坑,没有告诉你一个实验相关的仪器数量,数据似乎有多余空格,读优改了半个下午,最后的方案是读入时判断这个数前后是否有换行符。
    2.以前Dinic写的比较少,都是等Edmonds-Karp算法TLE以后才改成写Dinic,这样就造成我以前写的Dinic虽然都是错的,然而并没有被卡掉,现在才发现每次BFS以后都要对当前弧数组清零,因为上一次增广以后可能会有退流,这就导致原来不能走的边可以走了。
    3.这道题最后在洛谷、LOJ上都AC了,然而在CodeVS上却WA了两个点,然后也调不出来,后来发现据说是没有SPJ?

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<vector>
      5 #include<cstring>
      6 const int inf=0x7fffffff;
      7 const int EOLN=inf;
      8 bool newline;
      9 inline int getint() {
     10     newline=false;
     11     char ch;
     12     while(!isdigit(ch=getchar())) {
     13         if(ch=='
    ') return EOLN;
     14     }
     15     int x=ch^'0';
     16     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     17     if(ch=='
    ') newline=true;
     18     return x;
     19 }
     20 const int E=5200,V=102;
     21 int s,t;
     22 struct Edge {
     23     int from,to,remain;
     24 };
     25 Edge e[E];
     26 int sz=0;
     27 std::vector<int> g[V];
     28 inline void add_edge(const int u,const int v,const int w) {
     29     e[sz]=(Edge){u,v,w};
     30     g[u].push_back(sz);
     31     sz++;
     32 }
     33 int lev[V];
     34 unsigned cur[V]={0};
     35 inline void bfs() {
     36     for(int i=1;i<=t;i++) lev[i]=-1;
     37     lev[s]=0;
     38     std::queue<int> q;
     39     q.push(s);
     40     while(!q.empty()) {
     41          int x=q.front();
     42         q.pop();
     43         for(unsigned i=0;i<g[x].size();i++) {
     44             Edge &y=e[g[x][i]];
     45             if(y.remain&&!~lev[y.to]) {
     46                 lev[y.to]=lev[x]+1;
     47                 q.push(y.to);
     48             }
     49         }
     50     }
     51     memset(cur,0,sizeof cur);
     52 }
     53 int dfs(const int x,const int flow) {
     54     if(x==t) return flow;
     55     for(unsigned &i=cur[x];i<g[x].size();i++) {
     56         Edge &y=e[g[x][i]];
     57         if(y.remain&&lev[x]<lev[y.to]) {
     58             if(int f=dfs(y.to,std::min(flow,y.remain))) {
     59                 e[g[x][i]].remain-=f;
     60                 e[g[x][i]^1].remain+=f;
     61                 return f;
     62             }
     63         }
     64     }
     65     return 0;
     66 }
     67 inline int Dinic() {
     68     int maxflow=0;
     69     for(;;) {
     70         bfs();
     71         if(!~lev[t]) break;
     72         while(int flow=dfs(s,inf)) {
     73             maxflow+=flow;
     74         }
     75     }
     76     return maxflow;
     77 }
     78 int main() {
     79     int n=getint(),m=getint();
     80     if(!newline) getint();
     81     s=0,t=n+m+1;
     82     int sum=0;
     83     for(int i=1;i<=n;i++) {
     84         int w=getint();
     85         sum+=w;
     86         add_edge(s,i,w);
     87         add_edge(i,s,0);
     88         if(newline) break;
     89         for(int j=getint();j!=EOLN;j=getint()) {
     90             add_edge(i,n+j,inf);
     91             add_edge(n+j,i,0);
     92             if(newline) break;
     93         }
     94     }
     95     for(int i=1;i<=m;i++) {
     96         add_edge(n+i,t,getint());
     97         add_edge(t,n+i,0);
     98     }
     99     int ans=sum-Dinic();
    100     for(int i=1;i<=n;i++) {
    101         if(~lev[i]) printf("%d ",i);
    102     }
    103     puts("");
    104     for(int i=1;i<=m;i++) {
    105         if(~lev[n+i]) printf("%d ",i);
    106     }
    107     puts("");
    108     printf("%d
    ",ans);
    109     return 0;
    110 }
  • 相关阅读:
    Python标准模块--logging
    Spark中决策树源码分析
    常见的相似或相异程度计算方法
    mpi4py实践
    集成学习
    决策树
    git使用
    Ubuntu 14.04 64bit 安装tensorflow(GPU版本)
    KNN算法
    一致性哈希算法原理及其在分布式系统中的应用
  • 原文地址:https://www.cnblogs.com/skylee03/p/7461427.html
Copyright © 2011-2022 走看看