首页 > 其他 > 详细

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

时间:2019-07-13 20:21:39      阅读:106      评论:0      收藏:0      [点我收藏+]

最大权闭合子图,正连$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;
  }
  void ddfs(int x,int c) {
    col[x]=c;
    for (ri i=0;i<ed[x].size();i++) {
      int e=ed[x][i];
      if (e%2==0 && !w[e] || e%2==1 && !w[e-1]) continue;
      if (col[to[e]]!=c) ddfs(to[e],c);
    }
  }
} 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;
}

 

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

原文:https://www.cnblogs.com/shxnb666/p/11181845.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!