网络流24题(不定期更新)
网络流讲解(感谢我学长的博客,安利一手)
板子题:
P3376 【模板】网络最大流
P2740 [USACO4.2]草地排水Drainage Ditches
// ============================================================
// #pragma GCC optimize(2)
// #pragma GCC optimize(3,"Ofast","inline")
// ============================================================
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <bitset>
#include <map>
#include <utility>
using namespace std;
const int maxn=1e6+10;
const long long int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-6;
//
template<class T>
inline void read(T &res)
{
char c;
T flag=1;
while((c=getchar())<'0'||c>'9') if(c=='-') flag=-1; res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0'; res*=flag;
}
template<class T>
void write(T res)
{
if(res<0) res=-res,putchar('-');
if(res>=10) write(res/10);
putchar('0'+res%10);
}
//
int n,m,s,t;
long long int ans,dis[maxn];
struct node
{
int to;
int nxt;
long long int val;
}E[maxn];
int tot=1;
int now[maxn],head[maxn];
inline void add(int u,int v,long long int w)
{
E[++tot].to=v;
E[tot].val=w;
E[tot].nxt=head[u];
head[u]=tot;
E[++tot].to=u;
E[tot].val=0ll;
E[tot].nxt=head[v];
head[v]=tot;
}
int BFS()
{
for(register int i=1;i<=n;i++) dis[i]=INF;
queue<int> Q;
Q.push(s);
dis[s]=0;
now[s]=head[s];
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for(register int i=head[x];i;i=E[i].nxt)
{
int v=E[i].to;
if(E[i].val>0 && dis[v]==INF)
{
Q.push(v);
now[v]=head[v];
dis[v]=dis[x]+1;
if(v==t) return 1;
}
}
}
return 0;
}
int DFS(int x,long long int sum)
{
if(x==t) return sum;
long long int k,res=0;
for(register int i=now[x];i && sum;i=E[i].nxt)
{
now[x]=i;
int v=E[i].to;
if(E[i].val>0 && (dis[v]==dis[x]+1))
{
k=DFS(v,min(sum,E[i].val));
if(k==0) dis[v]=INF;
E[i].val-=k;
E[i^1].val+=k;
res+=k;
sum-=k;
}
}
return res;
}
int main()
{
//============================================================
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//============================================================
#ifdef LOCAL
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
//============================================================
cin >> n >> m >> s >> t;
for(register int i=1;i<=m;i++)
{
int u,v;
long long int w;
cin >> u >> v >> w;
add(u,v,w);
}
while(BFS()) ans+=DFS(s,INF);
cout << ans << endl;
return 0;
}
- P2756 飞行员配对方案问题
这道题可以跑最大流,当然也可以用二分图匹配(匈牙利算法)。如果跑最大流的话最主要的问题是如何建图?
设置出两个点,一个是超级原点S,一个是超级原点T,将S与1 ~ m建立一条值为1的边,m+1 ~ n与T同理。
之后跑Dinic板子。
// ============================================================
// #pragma GCC optimize(2)
// #pragma GCC optimize(3,"Ofast","inline")
// ============================================================
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <bitset>
#include <map>
#include <utility>
using namespace std;
const int maxn=1e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-6;
//
template<class T>
inline void read(T &res)
{
char c;
T flag=1;
while((c=getchar())<'0'||c>'9') if(c=='-') flag=-1; res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0'; res*=flag;
}
template<class T>
void write(T res)
{
if(res<0) res=-res,putchar('-');
if(res>=10) write(res/10);
putchar('0'+res%10);
}
//
int n,m,s,t;
struct node
{
int to;
int nxt;
int val;
}E[maxn];
int tot=1;
int head[maxn],now[maxn];
int dis[maxn];
int ans=0;
inline void add(int u,int v,int w)
{
E[++tot].to=v;
E[tot].val=w;
E[tot].nxt=head[u];
head[u]=tot;
E[++tot].to=u;
E[tot].val=0;
E[tot].nxt=head[v];
head[v]=tot;
}
inline bool BFS()
{
memset(dis,-1,sizeof(dis));
queue<int> Q;
Q.push(s);
dis[s]=0;
now[s]=dis[s];
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for(register int i=head[x];i;i=E[i].nxt)
{
int v=E[i].to;
if(E[i].val && dis[v]==-1)
{
dis[v]=dis[x]+1;
now[v]=head[v];
Q.push(v);
}
}
}
if(dis[t]!=-1) return 1;
return 0;
}
int DFS(int x,int flow)
{
if(x==t) return flow;
int k,res=0;
for(register int i=head[x];i && flow;i=E[i].nxt)
{
int v=E[i].to;
if(dis[v]==dis[x]+1 && E[i].val)
{
k=DFS(v,min(flow-res,E[i].val));
E[i].val-=k;
E[i^1].val+=k;
res+=k;
if(res==flow) return flow;
}
}
if(res==0) dis[x]=-1;
return res;
}
inline void Dinic()
{
while(BFS()) ans+=DFS(s,INF);
}
int main()
{
//============================================================
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//============================================================
#ifdef LOCAL
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
//============================================================
cin >> m >> n;
s=0,t=n+1;
while(1)
{
int u,v;
cin >> u >> v;
if(u==-1 && v==-1) break;
add(u,v,1);
}
for(register int i=1;i<=m;i++) add(s,i,1);
for(register int i=m+1;i<=n;i++) add(i,t,1);
Dinic();
if(ans==0)
{
cout << "No Solution!" << endl;
return 0;
}
cout << ans << endl;
for(register int i=2;i<=tot;i+=2)
{
if((E[i].to!=s && E[i^1].to!=s) && (E[i].to!=t && E[i^1].to!=t) && E[i^1].val!=0)
{
cout << E[i^1].to << " " << E[i].to << endl;
}
}
return 0;
}