一.多源汇点
题目:
多个源点,不就是这几个源点的流量是不守恒的吗,我们直接建立超级源点和汇点,跑dinic即可。因为多个源汇点的流始终是单向的,我们只需要提供一个起始点和承接点即可
代码如下:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e4+10,M=(2*N+1e5+10)*2,INF=1e9;
int S,T;
int h[N],ne[M],e[M],f[M],idx;
int d[N],cur[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(){
memset(d,-1,sizeof d);
queue<int>q;
q.push(S);
cur[S]=h[S];d[S]=0;
while(!q.empty()){
int t=q.front();
q.pop();
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.push(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];
cur[u]=i;
if(d[ver]==d[u]+1 && f[i]){
int t=find(ver,min(f[i],limit-flow));
if(!t)d[ver]=-1;
f[i]-=t;f[i^1]+=t;flow+=t;
}
}
return flow;
}
int dinic(){
int res=0,flow=0;
while(bfs())while(flow=find(S,INF))res+=flow;
return res;
}
int main(){
memset(h,-1,sizeof h);
int n,m,s,t;
cin>>n>>m>>s>>t;
S=0,T=n+1;
for(int i=0; i<s; i++){
int tt;
cin>>tt;
add(S,tt,INF);
}
for(int i=0; i<t; i++){
int tt;
cin>>tt;
add(tt,T,INF);
}
for(int i=0; i<m; i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
cout<<dinic()<<endl;
}
二.关键边
题目:
无非就是增加一条边,然后是否有增广路的情况;
下面给出一个O(n^2*m)的做法,对于一条边,我们扩大容量,是否有增广路。首先我们先跑一遍dinic求残余网络。然后对于每一条容量为0的边u->v(>0的边一定没有增广路了),查看从源点S是否能到u,和从v是否能到T;如果条件满足,那就存在增广路;
代码实现如下:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e4+10,M=(2*N+1e5+10)*2,INF=1e9;
int S,T;
int h[N],ne[M],e[M],f[M],idx;
int d[N],cur[N];
bool vis_s[N],vis_t[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(){
memset(d,-1,sizeof d);
queue<int>q;
q.push(S);
cur[S]=h[S];d[S]=0;
while(!q.empty()){
int t=q.front();
q.pop();
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.push(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];
cur[u]=i;
if(d[ver]==d[u]+1 && f[i]){
int t=find(ver,min(f[i],limit-flow));
if(!t)d[ver]=-1;
f[i]-=t;f[i^1]+=t;flow+=t;
}
}
return flow;
}
int dinic(){
int res=0,flow=0;
while(bfs())while(flow=find(S,INF))res+=flow;
return res;
}
void dfs(int u, bool st[], int fla){
st[u]=true;
for(int i=h[u]; ~i; i=ne[i]){
int ver=e[i];
int j=i^fla;
if(f[j] && !st[ver]){
dfs(ver,st,fla);
}
}
}
int main(){
memset(h,-1,sizeof h);
int n,m;
cin>>n>>m;
S=0,T=n-1;
for(int i=0; i<m; i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
dinic();
dfs(S,vis_s,0);
dfs(T,vis_t,1);
int res=0;
for(int i=0; i<2*m; i+=2){
if(!f[i] && vis_t[e[i]] && vis_s[e[i^1]]){
res++;
}
}
cout<<res<<endl;
}