上下界网络流总结

$orz$ $zhhx$

$orz$ $yyb$

$orz$ $AYSN$

无源汇可行流:每条边取$L[i] + $最大流调整

有源汇可行流:$E + (T,S,INF) + $无源汇可行流

有源汇最小流:有源汇可行流(去掉$INF$边)$- T \rightarrow S$最大流

有源汇最大流:有源汇可行流(去掉$INF$边)$+ S \rightarrow T$最大流

上下界网络流,不过于此。


 

有源汇最小流

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<queue>
#include<cstdlib>
#define LL long long
#define N 50005
#define M 150005
#define INF 1000000000000007LL
#define ri register int
using namespace std;

int n,m,s,t;
int u[M],v[M],l[M],r[M];
LL p[N];

struct graph {
  vector<int> to,ed[N];
  vector<LL> w;
  int cur[N],d[N];
  int S,T;
  void add_edge(int u,int v,LL 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);
  }
  void add_edges(int u,int v,LL w1,LL w2) {
    to.push_back(v); w.push_back(w1); ed[u].push_back(to.size()-1);
    to.push_back(u); w.push_back(w2); ed[v].push_back(to.size()-1);
  }
  bool bfs() {
    queue<int> q;
    memset(d,0x3f,sizeof(d));
    d[S]=0; q.push(S);
    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]<1000000007;
  }
  LL dfs(int x,LL limit) {
    if (x==T || !limit) return limit;
    LL 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]) {
        LL 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;
  }
  LL dinic() {
    LL ret=0;
    while (bfs()) {
      memset(cur,0,sizeof(cur));
      ret+=dfs(S,INF);
    }
    return ret;
  }
} G,G2;

int main() {
  scanf("%d %d %d %d",&n,&m,&s,&t);
  for (ri i=1;i<=m;i++) {
    scanf("%d %d %d %d",&u[i],&v[i],&l[i],&r[i]);
    p[u[i]]-=l[i],p[v[i]]+=l[i];
  }
  LL sum=0;
  for (ri i=1;i<=m;i++) G2.add_edge(u[i],v[i],r[i]-l[i]);
  for (ri i=1;i<=n;i++) {
    if (p[i]>0) sum+=p[i],G2.add_edge(0,i,p[i]);
    else if (p[i]<0) G2.add_edge(i,n+1,-p[i]);
  }
  G2.add_edge(t,s,INF);
  G2.S=0; G2.T=n+1;
  if (G2.dinic()<sum) {
    puts("please go home to sleep");
    return 0;
  }
  LL flow1=G2.w[G2.w.size()-1];
  for (ri i=1;i<=n;i++) {
    for (ri j=0;j<G2.ed[i].size();j++) {
      int e=G2.ed[i][j];
      if (e%2==0&&0<=e/2&&e/2<m) G.add_edges(i,G2.to[e],G2.w[e],r[e/2+1]-l[e/2+1]-G2.w[e]);
    }
  }
  G.S=t; G.T=s;
  cout<<flow1-G.dinic()<<endl;
  return 0;
}

有源汇最大流

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<queue>
#include<cstdlib>
#define LL long long
#define N 50005
#define M 150005
#define INF 1000000000000007LL
#define ri register int
using namespace std;

int n,m,s,t;
int u[M],v[M],l[M],r[M];
LL p[N];

struct graph {
  vector<int> to,ed[N];
  vector<LL> w;
  int cur[N],d[N];
  int S,T;
  void add_edge(int u,int v,LL 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);
  }
  void add_edges(int u,int v,LL w1,LL w2) {
    to.push_back(v); w.push_back(w1); ed[u].push_back(to.size()-1);
    to.push_back(u); w.push_back(w2); ed[v].push_back(to.size()-1);
  }
  bool bfs() {
    queue<int> q;
    memset(d,0x3f,sizeof(d));
    d[S]=0; q.push(S);
    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]<1000000007;
  }
  LL dfs(int x,LL limit) {
    if (x==T || !limit) return limit;
    LL 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]) {
        LL 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;
  }
  LL dinic() {
    LL ret=0;
    while (bfs()) {
      memset(cur,0,sizeof(cur));
      ret+=dfs(S,INF);
    }
    return ret;
  }
} G,G2;

int main() {
  scanf("%d %d %d %d",&n,&m,&s,&t);
  for (ri i=1;i<=m;i++) {
    scanf("%d %d %d %d",&u[i],&v[i],&l[i],&r[i]);
    p[u[i]]-=l[i],p[v[i]]+=l[i];
  }
  LL sum=0;
  for (ri i=1;i<=m;i++) G2.add_edge(u[i],v[i],r[i]-l[i]);
  for (ri i=1;i<=n;i++) {
    if (p[i]>0) sum+=p[i],G2.add_edge(0,i,p[i]);
    else if (p[i]<0) G2.add_edge(i,n+1,-p[i]);
  }
  G2.add_edge(t,s,INF);
  G2.S=0; G2.T=n+1;
  if (G2.dinic()<sum) {
    puts("please go home to sleep");
    return 0;
  }
  LL flow1=G2.w[G2.w.size()-1];
  for (ri i=1;i<=n;i++) {
    for (ri j=0;j<G2.ed[i].size();j++) {
      int e=G2.ed[i][j];
      if (e%2==0&&0<=e/2&&e/2<m) G.add_edges(i,G2.to[e],G2.w[e],r[e/2+1]-l[e/2+1]-G2.w[e]);
    }
  }
  G.S=s; G.T=t;
  cout<<flow1+G.dinic()<<endl;
  return 0;
}
posted @ 2019-07-20 19:24  HellPix  阅读(237)  评论(0)    收藏  举报