$orz$ $zhhx$
$orz$ $yyb$
$orz$ $AYSN$
无源汇可行流:每条边取$L[i] + $最大流调整
有源汇可行流:$E + (T,S,INF) + $无源汇可行流
有源汇最小流:有源汇可行流(去掉$INF$边)$- T ightarrow S$最大流
有源汇最大流:有源汇可行流(去掉$INF$边)$+ S ightarrow 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; }