• 【网络流24题】太空计划问题


    题面

    https://www.luogu.org/problemnew/show/P2762

    最大权闭合子图,正连$S$,负连$T$。

    注意最小割方案的输出(摘自刘汝佳《紫书》)。

    一个割,就是把点集$V$分成$S$和$T$,让$s in S$,$t in T$,割的流量就是跨越$S$和$T$的所有边的容量之和。

    最后一次$bfs$结束之后,有标号的点在$S$中,没标号的点($d[x]=INF$)在$T$中。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<queue>
    #define ri register int
    #define N 200
    #define INF 1000000007
    #define S 0
    #define T (n+m+1)
    using namespace std;
    
    int m,n,x;
    char tools[10000];
    int an[N];
    
    struct graph {
      vector<int> to,w;
      vector<int> ed[N];
      int cur[N],d[N],col[N];
      void add_edge(int u,int v,int w1) {
        to.push_back(v); w.push_back(w1); ed[u].push_back(to.size()-1);
        to.push_back(u); w.push_back(0 ); ed[v].push_back(to.size()-1);
      }
      bool bfs() {
        queue<int> q;
        memset(d,0x3f,sizeof(d));
        d[0]=0; q.push(0);
        while (!q.empty()) {
          int x=q.front(); q.pop();
          for (ri i=0,l=ed[x].size();i<l;i++) {
            int e=ed[x][i];
            if (w[e] && d[x]+1<d[to[e]]) {
              d[to[e]]=d[x]+1;
              q.push(to[e]);
            }
          }
        }
        return d[T]<INF;
      }
      int dfs(int x,int limit) {
        if (x==T || !limit) return limit;
        int tot=0;
        for (ri &i=cur[x];i<ed[x].size();i++) {
          int e=ed[x][i];
          if (d[to[e]]==d[x]+1 && w[e]) {
            int f=dfs(to[e],min(limit,w[e]));
            if (!f) continue;
            w[e]-=f; w[1^e]+=f; 
            tot+=f; limit-=f;
            if (!limit) return tot;
          }
        }
        return tot;
      }
      int dinic() {
        int ret=0;
        while (bfs()) {
          memset(cur,0,sizeof(cur));
          ret+=dfs(S,INF);
        }
        return ret;
      }
    } G;
    
    int main(){
      cin>>m>>n;
      int sum=0;
      for (ri i=1;i<=m;i++) {
        cin>>x;
        sum+=x;
        G.add_edge(S,i,x);
        memset(tools,0,sizeof tools);
        cin.getline(tools,10000);
        int ulen=0,tool;
        while (sscanf(tools+ulen,"%d",&tool)==1) {
          if (tool==0) ulen++;
          else {
            G.add_edge(i,m+tool,INF);
            while (tool) tool/=10,ulen++;
          }
          ulen++;
        }
      }
      for (ri i=1;i<=n;i++) cin>>x,G.add_edge(m+i,T,x);
      int ans=sum-G.dinic();
      for (ri i=0;i<G.to.size();i+=2) {
        if (G.d[G.to[i]]<INF^G.d[G.to[i^1]]<INF) {
          if (G.to[i]==S) an[G.to[i^1]]=1;
          if (G.to[i^1]==S) an[G.to[i]]=1;
          if (G.to[i]==T) an[G.to[i^1]]=1;
          if (G.to[i^1]==T) an[G.to[i]]=1;
        }
      }
      for (ri i=1;i<=m;i++) if (!an[i]) cout<<i<<" "; puts("");
      for (ri i=1;i<=n;i++) if (an[i+m]) cout<<i<<" "; puts("");
      cout<<ans<<endl;
    }
  • 相关阅读:
    poj 2996 模拟
    poj 2965 BFS
    poj 1068 模拟
    poj 3295 前缀表达式求值
    常用的十七大学术搜索引擎
    Why,Unix or Linux ?
    匈牙利命名法
    微调控件(CSpinButtonCtrl)
    美国免费邮箱
    ASP常用的代码
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11181845.html
Copyright © 2020-2023  润新知