【HDOJ 1532】 Drainage Ditches(最大流模板)
最大流模板题 邻接矩阵建图的话注意重边就好 那来存最大流模板吧
顺记几篇好文:http://blog.sina.com.cn/s/blog_92fcae85010135mm.html
http://blog.csdn.net/u010787640/article/details/12218719
http://www.cnblogs.com/wally/archive/2013/05/03/3054778.html
http://www.cnblogs.com/georgechen-ena/archive/2011/11/07/2240185.html
http://www.cnblogs.com/wally/p/3274438.html
http://www.cnblogs.com/longdouhzt/archive/2012/05/20/2510753.html
朴素dfs:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;
typedef struct Edge
{
int t,cap,rev;
}Edge;
vector <Edge> head[233];
bool vis[233];
int n;
void Add(int fm,int to,int cap)
{
head[fm].push_back(Edge {to,cap,head[to].size()});
head[to].push_back(Edge {fm,0,head[fm].size()-1});
}
int dfs(int s,int t,int f)
{
int i;
if(s == t)
return f;
vis[s] = true;
for(i = 0; i < head[s].size(); ++i)
{
Edge &tmp = head[s][i];
if(!vis[tmp.t] && tmp.cap > 0)
{
int d = dfs(tmp.t,t,min(f,tmp.cap));
if(d > 0)
{
tmp.cap -= d;
head[tmp.t][tmp.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow()
{
int f,flow = 0;
while(1)
{
memset(vis,0,sizeof(vis));
f = dfs(1,n,INF);
if(f) flow += f;
else return flow;
}
}
int main()
{
int m,u,v,w;
while(~scanf("%d %d",&m,&n))
{
memset(head,0,sizeof(head));
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
Add(u,v,w);
}
printf("%d\n",max_flow());
}
return 0;
}
朴素bfs:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
int mp[233][233];
int flow[233],pre[233];
int n;
int bfs()
{
queue <int> q;
memset(pre,-1,sizeof(pre));
q.push(1);
flow[1] = INF;
pre[1] = 0;
int u,v,i;
while(!q.empty())
{
u = q.front();
q.pop();
if(u == n) return flow[u];
for(i = 1; i <= n; ++i)
{
if(pre[i] == -1 && mp[u][i] > 0)
{
flow[i] = min(mp[u][i],flow[u]);
pre[i] = u;
q.push(i);
}
}
}
if(pre[n] = -1) return 0;
return flow[n];
}
int max_flow()
{
int f,sumflow = 0;
while((f = bfs()) != 0)
{
int k = n;
while(k != 1)
{
int last = pre[k];
mp[last][k] -= f;
mp[k][last] += f;
k = last;
}
sumflow += f;
}
return sumflow;
}
int main()
{
int m,u,v,w;
while(~scanf("%d %d",&m,&n))
{
memset(mp,0,sizeof(mp));
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
if(u == v) continue;
mp[u][v] += w;
}
printf("%d\n",max_flow());
}
return 0;
}
朴素 dinic:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
typedef struct Edge
{
int to,cap,rev;
}Edge;
int dis[233];
vector <Edge> head[233];
int n,m;
void Add(int u,int v,int w)
{
head[u].push_back(Edge{v,w,head[v].size()});
head[v].push_back(Edge{u,0,head[u].size()-1});
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue <int> q;
q.push(1);
dis[1] = 0;
int u,v,w,i;
while(!q.empty())
{
u = q.front();
q.pop();
for(i = 0; i < head[u].size(); ++i)
{
v = head[u][i].to;
if(head[u][i].cap >0 && dis[v] == -1)
{
dis[v] = dis[u]+1;
q.push(v);
}
}
}
return (dis[n] != -1);
}
int Maxflow(int u,int flow)
{
if(u == n) return flow;
int i,v,w,id,x;
for(i = 0; i < head[u].size(); ++i)
{
v = head[u][i].to;
w = head[u][i].cap;
id = head[u][i].rev;
if(dis[v] == dis[u]+1 && (x = Maxflow(v,min(flow,w))))
{
head[u][i].cap -= x;
head[v][id].cap += x;
return x;
}
}
return 0;
}
int main()
{
int u,v,w,flow,sumflow;
while(~scanf("%d %d",&m,&n))
{
memset(head,0,sizeof(head));
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
Add(u,v,w);
}
sumflow = 0;
while(bfs())
{
while(flow = Maxflow(1,INF)) sumflow += flow;
}
printf("%d\n",sumflow);
}
return 0;
}
dinic+当前弧优化:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
int dis[233],dq[233],mp[233][233];
int n,m;
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue <int> q;
q.push(1);
dis[1] = 0;
int u,v,w,i;
while(!q.empty())
{
u = q.front();
q.pop();
for(i = 1; i <= n; ++i)
{
if(mp[u][i] > 0 && dis[i] == -1)
{
dis[i] = dis[u]+1;
q.push(i);
}
}
}
return (dis[n] != -1);
}
int Maxflow(int u,int flow)
{
if(u == n) return flow;
int i,x;
for(i = dq[u];i < n; ++i)
{
dq[u] = i;
if(dis[i+1] == dis[u]+1 && mp[u][i+1] && (x = Maxflow(i+1,min(flow,mp[u][i+1]))))
{
mp[u][i+1] -= x;
mp[i+1][u] += x;
return x;
}
}
return 0;
}
int main()
{
int u,v,w,flow,sumflow;
while(~scanf("%d %d",&m,&n))
{
memset(mp,0,sizeof(mp));
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
mp[u][v] += w;
}
sumflow = 0;
while(bfs())
{
memset(dq,0,sizeof(dq));
while(flow = Maxflow(1,INF)) sumflow += flow;
}
printf("%d\n",sumflow);
}
return 0;
}
dinic多路增广
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
int dis[233],mp[233][233];
int n,m;
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue <int> q;
q.push(1);
dis[1] = 0;
int u,v,w,i;
while(!q.empty())
{
u = q.front();
q.pop();
for(i = 1; i <= n; ++i)
{
if(mp[u][i] > 0 && dis[i] == -1)
{
dis[i] = dis[u]+1;
q.push(i);
}
}
}
return (dis[n] != -1);
}
int Maxflow(int u,int flow)
{
if(u == n) return flow;
int i,x,sum;
for(i = 1; sum < flow && i <= n; ++i)
{
if(dis[i] == dis[u]+1 && mp[u][i] && (x = Maxflow(i,min(flow-sum,mp[u][i]))))
{
mp[u][i] -= x;
mp[i][u] += x;
sum += x;
}
}
if(!sum) dis[i] = -2;
return sum;
}
int main()
{
int u,v,w,flow,sumflow;
while(~scanf("%d %d",&m,&n))
{
memset(mp,0,sizeof(mp));
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
mp[u][v] += w;
}
sumflow = 0;
while(bfs())
{
sumflow += Maxflow(1,INF);
}
printf("%d\n",sumflow);
}
return 0;
}
邻接矩阵sap+gap+当前弧优化
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
int mp[233][233],gap[233],level[233],pre[233],cur[233];
int n,m;
int sap()
{
memset(gap,0,sizeof(gap));//层次找断点
memset(level,0,sizeof(level));//高度
memset(cur,0,sizeof(cur));//当前弧
int u,v,sumflow = 0,flow = INF,f;
gap[0] = n;
u = pre[1] = 1;
while(level[1] < n)
{
for(v = cur[u]; v <= n; ++v)//找当前点的前一级
{
cur[u] = v;
if(mp[u][v] && level[u] == level[v] +1) break;
}
if(v <= n)
{
flow = min(flow,mp[u][v]);
pre[v] = u;
u = v;
if(v == n)
{
sumflow += flow;
for(u = pre[v]; v != 1; v = u, u = pre[u])
{
mp[u][v] -= flow;
mp[v][u] += flow;
}
flow = INF;
}
}
else
{
f = n;
for(v = 1; v <= n; ++v)//找离当前点最近的点
{
if(mp[u][v] && f > level[v])
{
cur[u] = v;
f = level[v];
}
}
if(!(--gap[level[u]])) break;//断点跳出
level[u] = f+1;
gap[level[u]]++;
u = pre[u];
}
}
return sumflow;
}
int main()
{
int u,v,w;
while(~scanf("%d %d",&m,&n))
{
memset(mp,0,sizeof(mp));
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
mp[u][v] += w;
}
printf("%d\n",sap());
}
return 0;
}
邻接表sap+gap+当前弧优化
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
typedef struct Edge
{
int to,cap,next;
}Edge;
Edge eg[233];
int head[444],level[233],gap[233],cur[233],pre[233];
int n,m,tp;
void Add(int u,int v,int w)
{
eg[tp].to = v;
eg[tp].cap = w;
eg[tp].next = head[u];
head[u] = tp++;
}
int sap()
{
memset(gap,0,sizeof(gap));
memset(level,0,sizeof(level));
int u,v,sumflow = 0,flow = INF,f;
gap[0] = n;
u = pre[1] = 1;
while(level[1] < n)
{
for(int &i = cur[u]; i != -1; i = eg[i].next)
{
v = eg[i].to;
if(eg[i].cap && level[u] == level[v] + 1) break;
}
if(cur[u] != -1)
{
v = cur[u];
flow = min(flow,eg[v].cap);
pre[eg[v].to] = u;
u = eg[v].to;
if(u == n)
{
sumflow += flow;
v = eg[v].to;
for(; u != 1;u = pre[u])
{
eg[cur[pre[u]]].cap -= flow;
eg[cur[pre[u]]^1].cap += flow;
}
flow = INF;
}
}
else
{
f = INF;
for(int i = head[u]; i != -1; i = eg[i].next)
{
if(eg[i].cap && f > level[eg[i].to])
{
cur[u] = i;
f = level[eg[i].to];
}
}
if(!(--gap[level[u]])) break;
level[u] = f + 1;
gap[level[u]]++;
u = pre[u];
}
}
return sumflow;
}
int main()
{
int u,v,w;
while(~scanf("%d %d",&m,&n))
{
memset(head,-1,sizeof(head));
tp = 0;
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
Add(u,v,w);
Add(v,u,0);
}
printf("%d\n",sap());
}
return 0;
}