终于开始蛋疼的网络流之旅了,鄙人最讨厌的事情莫过于新学一套算法,但随着网络流算法的普及,越来越多的题目都
开始用到网络流,今年暑假的一次多校赛上居然有两道做法差不多的网络流题目,真是丧心病狂,让我等网络流没学过的人如何存活。。
所以今天学了最简单的最大流FORD算法,我对它的初步印象(注意,不一定正确),大概它不能处理负边,负边得额外处理。DFS实现它虽然写起来简易,但效率实在太低,故必须用BFS实现。网络流多为有向边(至少今天做的两题是的。),BFS过程中你会发现它相连了两个反向边连接的点,你不用疑惑,因为此时它的流也是负的,它这么做是模拟之前流入量减少从而来查找增广路的过程。算法简单,建图永远是关键,这需要长期做题的积累和对流的敏感度。
两道网络流水题:
POJ 1149
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<string>
#include<cstring>
#include<algorithm>
#include<fstream>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#include<iomanip>
#define rep(i,n) for(i=1;i<=n;i++)
#define MM(a,t) memset(a,t,sizeof(a))
#define INF 1e9
typedef long long ll;
#define mod 1000000007
using namespace std;
int pan[120][120];
int liu[1010],a[1010];
int minflow[120],flow[120][120],pr[120];
queue<int> Q;
int n,m;
void FORD(int st,int t){
int i,j;
for(i=0;i<=m+1;i++)
for(j=0;j<=m+1;j++)
flow[i][j]=0;
minflow[st]=INF;
while(1){
pr[st]=-1;
rep(i,m+1) pr[i]=-2;
while(!Q.empty()) Q.pop();
Q.push(st);
while(!Q.empty() && pr[t]==-2){
int s=Q.front(),e,tmp; Q.pop();
for(e=0;e<=m+1;e++)
if(pr[e]==-2 &&(tmp=pan[s][e]-flow[s][e])>0){
pr[e]=s; Q.push(e);
minflow[e]=min(minflow[s],tmp);
}
}
if(pr[t]==-2) break;
for(i=pr[t],j=t;i!=-1;j=i,i=pr[i])
{
flow[i][j]=flow[i][j]+minflow[t];
flow[j][i]=-flow[i][j];
}
}
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
MM(a,0); MM(pan,0);
rep(i,n) scanf("%d",&liu[i]);
rep(i,m){
scanf("%d",&j);
while(j--){
int tmp;
scanf("%d",&tmp);
if(a[tmp]==0){
pan[0][i]+=liu[tmp];
a[tmp]=i;
}
else{
pan[a[tmp]][i]=INF;
a[tmp]=i;
}
}
scanf("%d",&pan[i][m+1]);
}
FORD(0,m+1);
int res=0;
rep(i,m) res+=flow[i][m+1];
cout<<res<<'\n';
}
return 0;
}
POJ1273
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<string>
#include<cstring>
#include<algorithm>
#include<fstream>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#include<iomanip>
#define rep(i,n) for(i=1;i<=n;i++)
#define MM(a,t) memset(a,t,sizeof(a))
#define INF 2*(1e9)+1
typedef long long ll;
#define mod 1000000007
using namespace std;
int pan[220][220];
vector<int> a[220];
int minflow[220],flow[220][220],pr[220];
queue<int> Q;
int n,m;
void FORD(int st,int t){
int i,j;
for(i=0;i<=n+1;i++)
for(j=0;j<=n+1;j++)
flow[i][j]=0;
minflow[st]=INF;
while(1){
pr[st]=-1;
for(i=2;i<=n;i++) pr[i]=-2;
while(!Q.empty()) Q.pop();
Q.push(st);
while(!Q.empty() && pr[t]==-2){
int s=Q.front(),e,tmp; Q.pop();
for(e=1;e<=n;e++){
if(pr[e]==-2 &&(tmp=pan[s][e]-flow[s][e])>0){
pr[e]=s; Q.push(e);
minflow[e]=min(minflow[s],tmp);
}
}
}
if(pr[t]==-2) break;
for(i=pr[t],j=t;i!=-1;j=i,i=pr[i])
{
flow[i][j]=flow[i][j]+minflow[t];
flow[j][i]=-flow[i][j];
}
}
}
int main()
{
int i,j;
while(scanf("%d%d",&m,&n)!=EOF){
rep(i,n) a[i].clear();
MM(pan,0);
rep(i,m){
int s,e,w;
scanf("%d%d%d",&s,&e,&w);
pan[s][e]+=w;
}
FORD(1,n);
int res=0;
for(i=1;i<=n-1;i++){
res+=flow[i][n];
}
cout<<res<<'\n';
}
return 0;
}