标签:style blog http io ar os sp for div
自NOIP 2014结束之后将近一个星期没撸题了,现在开始搞省选,发个水水的裸网络流题解吧。
题目链接:http://poj.org/problem?id=1273
裸网络流,模板题。
1、Edmond_Karp算法
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define MAXV 220
#define MAXE 220
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int cap[MAXV][MAXV],flow[MAXV][MAXV]; //容量、流量
int a[MAXV];
int last[MAXV];
int EdmondsKarp(int s,int t) //EK算法求s到t的最大流
{
int sum=0;
queue<int>q;
while(1)
{
while(!q.empty()) q.pop();
q.push(s);
memset(a,0,sizeof(a));
a[s]=INF;
while(!q.empty()) //找增广路
{
int u=q.front();
q.pop();
for(int v=1;v<=m;v++)
{
if(!a[v]&&flow[u][v]<cap[u][v])
{
last[v]=u;
q.push(v);
a[v]=min(a[u],cap[u][v]-flow[u][v]);
}
}
}
if(a[t]==0) //找不到增广路,则已经找到最大流
break;
sum+=a[t]; //加上这次增广得到的流量
for(int i=t;i!=s;i=last[i]) //根据增广路的链表顺着更新
{
flow[last[i]][i]+=a[t];
flow[i][last[i]]-=a[t];
}
}
return sum;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(cap,0,sizeof(cap));
memset(flow,0,sizeof(flow));
for(int i=1;i<=n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
cap[u][v]+=w;
}
printf("%d\n",EdmondsKarp(1,m));
}
return 0;
}
2、Dinic算法快速求网络流#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <deque>
#include <cstring>
#define mem(array,num) memset(array,num,sizeof(array))
#define MAXE 300
#define INF 0x3f3f3f3f
using namespace std;
int G[MAXE][MAXE];
bool visit[MAXE];
int Layer[300]; //Layer[i]=点i所在层数
int n,m;
bool CountLayer() //BFS对图进行分层
{
int layer=0;
deque<int>q;
mem(Layer,-1); //初始化所有层数都为-1
Layer[1]=0; //点1层数为0
q.push_back(1); //点1入队
while(!q.empty())
{
int now=q.front();
q.pop_front();
for(int j=1;j<=m;j++)
{
if(G[now][j]>0&&Layer[j]==-1) //now->j有剩余容量且j还没被访问过
{
Layer[j]=Layer[now]+1;
if(j==m) return true; //分层到达了汇点即可
else q.push_back(j);
}
}
}
return false; //到达不了汇点,返回false
}
int Dinic()
{
int i,s,maxFlow=0;
deque<int>q; //栈,DFS用
while(CountLayer()) //只要能分层
{
q.push_back(1); //源点入栈
mem(visit,0);
visit[1]=true;
while(!q.empty())
{
int top=q.back();
if(top==m) //top是汇点
{
int minC=INF; //在栈中找容量最小的边
int SminC; //容量最小的边的起点
for(int i=1;i<q.size();i++)
{
int vs=q[i-1];
int ve=q[i];
if(G[vs][ve]>0)
{
if(minC>G[vs][ve]) //更新最小容量边
{
minC=G[vs][ve];
SminC=vs;
}
}
}
//增广,改图
maxFlow+=minC;
for(int i=1;i<q.size();i++)
{
int vs=q[i-1];
int ve=q[i];
G[vs][ve]-=minC; //减少边容量
G[ve][vs]+=minC; //增加反向边
}
while(!q.empty()&&q.back()!=SminC) //退栈直到SminC成为栈顶,这样方便DFS
{
visit[q.back()]=false;
q.pop_back();
}
}
else //top不是汇点
{
int i;
for(i=1;i<=m;i++)
{
if(G[top][i]>0&&Layer[i]==Layer[top]+1&&!visit[i]) //只往下一层没有走过的节点走
{
visit[i]=1;
q.push_back(i);
break;
}
}
if(i>m) //找不到下一个点,则往回走
q.pop_back();
}
}
}
return maxFlow;
}
int main()
{
while(cin>>n>>m) //n边m点
{
mem(G,0);
for(int i=0;i<n;i++)
{
int u,v,c;
cin>>u>>v>>c;
G[u][v]+=c; //防止被坑,两点间可能有多条边,容量累加
}
cout<<Dinic()<<endl;
}
return 0;
}
[POJ 1273]Drainage Ditches(Edmond-Krap算法和Dinic算法求最大流)
标签:style blog http io ar os sp for div
原文地址:http://blog.csdn.net/qpswwww/article/details/41118481