最大流
最大流模板-Dinic
#include <bits/stdc++.h>
using namespace std;
const int N = 10010,M = 2e5+10,INF = 0x3f3f3f3f;
int h[N],e[M],ne[M],f[M],idx;
int q[N],d[N],cur[N];
int n,m,S,T;
void add(int a,int b,int c)
{
e[idx] = b,f[idx] = c,ne[idx] = h[a],h[a] = idx++;
e[idx] = a,f[idx] = 0,ne[idx] = h[b],h[b] = idx++;
}
bool bfs()
{
memset(d,-1,sizeof d);
int tt = 0,hh = 0;
q[0] = S,d[S] = 0,cur[S] = h[S];
while(tt>=hh)
{
int t = q[hh++];
for(int i = h[t];~i;i = ne[i])
{
int ver = e[i];
if(d[ver]==-1&&f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if(ver==T) return true;
q[++tt] = ver;
}
}
}
return false;
}
int find(int u,int limit)
{
if(u==T) return limit;
int flow = 0;
for(int i = cur[u];~i&&flow<limit;i = ne[i])
{
cur[u] = i;
int ver = e[i];
if(d[ver]==d[u]+1&&f[i])
{
int t = find(ver,min(limit-flow,f[i]));
if(!t) d[ver] = -1;
flow += t,f[i]-=t,f[i^1]+=t;
}
}
return flow;
}
int dinic()
{
int flow,r = 0;
while(bfs())while(flow = find(S,INF)) r += flow;
return r;
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d%d%d%d",&n,&m,&S,&T);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
printf("%d\n",dinic());
return 0;
}
上下界
无源汇上下界可行流
#include <bits/stdc++.h>
using namespace std;
const int N = 210,M = (10200+N)*2,INF = 0x3f3f3f3f;
int h[N],e[M],ne[M],f[M],l[M],idx;
int d[N],q[N],cur[N],A[N];
int n,m,S,T;
void add(int a,int b,int c,int d)
{
e[idx] = b,f[idx] = d-c,l[idx] = c,ne[idx] = h[a],h[a] = idx++;
e[idx] = a,f[idx] = 0,ne[idx] = h[b],h[b] = idx++;
}
bool bfs()
{
memset(d,-1,sizeof d);
int hh = 0,tt = 0;
q[0] = S,d[S] = 0,cur[S] = h[S];
while(hh<=tt)
{
int t = q[hh++];
for(int i = h[t];~i;i = ne[i])
{
int ver = e[i];
if(d[ver]==-1&&f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if(ver==T) return true;
q[++tt] = ver;
}
}
}
return false;
}
int find(int u,int limit)
{
if(u==T) return limit;
int flow= 0;
for(int i = cur[u];~i&&flow<limit;i = ne[i])
{
cur[u] = i;
int ver = e[i];
if(d[ver]==d[u]+1&&f[i])
{
int t = find(ver,min(f[i],limit-flow));
if(!t) d[ver] = -1;
flow += t,f[i] -=t,f[i^1]+=t;
}
}
return flow;
}
int dinic()
{
int r = 0,flow;
while(bfs()) while(flow=find(S,INF)) r += flow;
return r;
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d%d",&n,&m);
S = 0,T = n+1;
for(int i = 0;i<m;i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
add(a,b,c,d);
A[a] -= c,A[b] += c;
}
int tot = 0;
for(int i = 1;i<=n;i++)
{
if(A[i]>0) add(S,i,0,A[i]),tot += A[i];
else if(A[i]<0) add(i,T,0,-A[i]);
}
if(dinic()!=tot) puts("NO");
else
{
puts("YES");
for(int i = 0;i<2*m;i+=2)
{
printf("%d\n",f[i^1]+l[i]);
}
}
return 0;
}
有源汇上下界最大流
#include <bits/stdc++.h>
using namespace std;
const int N = 440,M = (10000+N) * 2,INF = 0x3f3f3f3f;
int h[N],e[M],f[M],ne[M],idx;
int d[N],cur[N],q[N],A[N];
int n,m,S,T;
void add(int a,int b,int c)
{
e[idx] = b,f[idx] = c,ne[idx] = h[a],h[a] = idx++;
e[idx] = a,f[idx] = 0,ne[idx] = h[b],h[b] = idx++;
}
bool bfs()
{
memset(d,-1,sizeof d);
int tt = 0,hh = 0;
q[0] = S,d[S] = 0,cur[S] = h[S];
while(tt>=hh)
{
int t = q[hh++];
for(int i = h[t];~i;i= ne[i])
{
int ver = e[i];
if(d[ver]==-1&&f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if(ver==T) return true;
q[++tt] = ver;
}
}
}
return false;
}
int find(int u,int limit)
{
if(u==T) return limit;
int flow = 0;
for(int i = cur[u];~i&&flow<limit;i = ne[i])
{
cur[u] = i;
int ver = e[i];
if(d[ver]==d[u]+1&&f[i])
{
int t = find(ver,min(limit-flow,f[i]));
if(!t) d[ver] = -1;
flow += t,f[i]-=t,f[i^1]+=t;
}
}
return flow;
}
int dinic()
{
int r = 0,flow;
while(bfs()) while(flow = find(S,INF)) r += flow;
return r;
}
int main()
{
memset(h,-1,sizeof h);
int s,t;
scanf("%d%d%d%d",&n,&m,&s,&t);
S = 0,T = n+1;
while(m--)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
add(a,b,d-c);
A[b] += c,A[a] -=c;
}
int tot = 0;
for(int i = 1;i<=n;i++)
{
if(A[i]>0) add(S,i,A[i]),tot+=A[i];
else if(A[i]<0) add(i,T,-A[i]);
}
add(t,s,INF);
if(dinic()<tot) puts("No Solution");
else
{
S = s,T = t;
int res = f[idx-1];
f[idx-1] = f[idx-2] = 0;
printf("%d\n",res+dinic());
}
return 0;
}
有源汇上下界最小流
#include <bits/stdc++.h>
using namespace std;
const int N = 500010,M = (N+125003) * 2,INF = 2147483647;
int h[N],e[M],ne[M],f[M],idx;
int q[N],cur[N],d[N],A[N];
int n,m,S,T;
void add(int a,int b,int c)
{
e[idx] = b,f[idx] = c,ne[idx] = h[a],h[a] = idx++;
e[idx] = a,f[idx] = 0,ne[idx] = h[b],h[b] = idx++;
}
bool bfs()
{
memset(d,-1,sizeof d);
int tt = 0,hh = 0;
q[0] = S,d[S] = 0,cur[S] = h[S];
while(hh<=tt)
{
int t = q[hh++];
for(int i = h[t];~i;i = ne[i])
{
int ver = e[i];
if(d[ver]==-1&&f[i])
{
cur[ver] = h[ver];
d[ver] = d[t] + 1;
if(ver==T) return true;
q[++tt] = ver;
}
}
}
return false;
}
int find(int u,int limit)
{
if(u==T) return limit;
int flow = 0;
for(int i = cur[u];~i&&flow<limit;i = ne[i])
{
cur[u] = i;
int ver = e[i];
if(d[ver]==d[u]+1&&f[i])
{
int t = find(ver,min(limit-flow,f[i]));
if(!t) d[ver] = -1;
f[i] -= t,flow += t,f[i^1]+=t;
}
}
return flow;
}
int dinic()
{
int r = 0,flow;
while(bfs()) while(flow=find(S,INF)) r += flow;
return r;
}
int main()
{
memset(h,-1,sizeof h);
int s,t;
scanf("%d%d%d%d",&n,&m,&s,&t);
S = 0,T = n+1;
while(m--)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
add(a,b,d-c);
A[a] -=c,A[b] += c;
}
int tot = 0;
for(int i = 1;i<=n;i++)
{
if(A[i]>0) add(S,i,A[i]),tot += A[i];
else if(A[i]<0) add(i,T,-A[i]);
}
add(t,s,INF);
if(dinic()!=tot) puts("No Solution");
else
{
int res = f[idx-1];
S = t,T = s;
f[idx-1] = f[idx-2] = 0;
printf("%d\n",res-dinic());
}
return 0;
}
最大流求解二分图匹配
思路大致是把所有匹配点分成两部分,S(源点)向左边的匹配点(可以自己定义),连一条容量为1的边,表示这个点有一个人,左边的匹配点向右边的可匹配点连一条容量是1的边(表示左边的人可以跟右边的人完成一次匹配),右边的匹配点向汇点T连一条容量是1的边
洛谷-飞行员匹配问题
#include <bits/stdc++.h>
using namespace std;
const int N = 110,M = 10010,INF = 0x3f3f3f3f;
int h[N],e[M],ne[M],f[M],idx;
int q[N],d[N],cur[N];
int n,m,S,T;
void add(int a,int b,int c)
{
e[idx] = b,f[idx] = c,ne[idx] = h[a],h[a] = idx++;
e[idx] = a,f[idx] = 0,ne[idx] = h[b],h[b] = idx++;
}
bool bfs()
{
memset(d,-1,sizeof d);
int tt = 0,hh = 0;
q[0] = S,d[S] = 0,cur[S] = h[S];
while(tt>=hh)
{
int t = q[hh++];
for(int i = h[t];~i;i = ne[i])
{
int ver = e[i];
if(f[i]&&d[ver]==-1)
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if(ver==T) return true;
q[++tt] = ver;
}
}
}
return false;
}
int find(int u,int limit)
{
if(u==T) return limit;
int flow = 0;
for(int i = cur[u];~i&&flow<limit;i = ne[i])
{
cur[u] = i;
int ver = e[i];
if(f[i]&&d[ver]==d[u]+1)
{
int t = find(ver,min(limit-flow,f[i]));
if(!t) d[ver] = -1;
flow += t,f[i] -= t,f[i^1]+=t;
}
}
return flow;
}
int dinic()
{
int r = 0,flow;
while(bfs())while(flow = find(S,INF)) r += flow;
return r;
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d%d",&m,&n);
S = 0,T = n+1;
for(int i = 1;i<=m;i++) add(S,i,1);
for(int i = m+1;i<=n;i++) add(i,T,1);
int a,b;
while(scanf("%d%d",&a,&b),a!=-1) add(a,b,1);
printf("%d\n",dinic());
for(int i = 0;i<idx;i+=2)
{
if(e[i]>m&&e[i]<=n&&!f[i])
{
printf("%d %d\n",e[i^1],e[i]);
}
}
return 0;
}
洛谷-圆桌问题
#include <bits/stdc++.h>
using namespace std;
const int N = 500,M = N*N,INF = 1e9;
int h[N],e[M],f[M],ne[M],idx;
int cur[N],q[N],d[N];
int n,m,S,T;
int r[N],des[N];
void add(int a,int b,int c)
{
e[idx] = b,f[idx] = c,ne[idx] = h[a],h[a] = idx++;
e[idx] = a,f[idx] = 0,ne[idx] = h[b],h[b] = idx++;
}
bool bfs()
{
int tt = 0,hh = 0;
memset(d,-1,sizeof d);
q[0] = S,d[S] = 0,cur[S] = h[S];
while(tt>=hh)
{
int t = q[hh++];
for(int i = h[t];~i;i = ne[i])
{
int ver = e[i];
if(d[ver] == -1&& f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if(ver==T) return true;
q[++tt] = ver;
}
}
}
return false;
}
int find(int u,int limit)
{
if(u == T) return limit;
int flow = 0;
for(int i = cur[u];~i&&flow<limit;i = ne[i])
{
int ver = e[i];
if(d[ver] == d[u] + 1 && f[i])
{
int t = find(ver,min(limit-flow,f[i]));
if(!t) d[ver] = -1;
f[i] -= t,f[i^1] += t,flow += t;
}
}
return flow;
}
int dinic()
{
int r = 0,flow;
while(bfs()) while(flow = find(S,INF)) r += flow;
return r;
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d%d",&m,&n);
S = 0,T = n+m+1;
int tot = 0;
for(int i = 1;i<=m;i++)
{
int x;
scanf("%d",&x);
add(S,i,x);
tot += x;
}
for(int i = 1;i<=n;i++)
{
int x;
scanf("%d",&x);
add(i+m,T,x);
}
for(int i = 1;i<=m;i++)for(int j = 1;j<=n;j++) add(i,j+m,1);
if(tot == dinic())
{
puts("1");
for(int i = 1;i<=m;i++)
{
for(int j = h[i];~j;j = ne[j])
{
if(e[j]>m&&e[j]<=m+n&&!f[j])
{
printf("%d ",e[j]-m);
}
}
puts("");
}
}
else puts("0");
return 0;
}
标签:ver,cur,idx,int,ne,网络,二三,++,关于
From: https://www.cnblogs.com/howardsblog/p/18011497