1. EK(Edmond—Karp)算法
poj1273
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define max(a,b) (a>b?a:b)
#define min(a,b) (a
#define swap(a,b) (a=a+b,b=a-b,a=a-b)
using namespace std;
typedef long long int LL;
const int MAXL(200);
const int INF(0x3f3f3f3f);
const int MAX(1e6);
const int mod(1e9+7);
int c[MAXL+50][MAXL+50];//残留网络的容量
int f[MAXL+50];//从源点到当前节点实际还剩多少流量可用
int pre[MAXL+50];//标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int m,n;//n个定点,m条边
int BFS(int sce,int des)
{
queue<int>q;
memset(pre,-1,sizeof(pre));//初始化pre数组
pre[sce]=0;
f[sce]=INF;
q.push(sce);
while(!q.empty())
{
int index=q.front();
q.pop();
if(index==des)
break;
for(int i=1;i<=n;i++)
{
if(i!=sce&&c[index][i]>0&&pre[i]==-1)
{
pre[i]=index;//记录前驱
f[i]=min(c[index][i],f[index]);//找增量
q.push(i);
}
}
}
return pre[des]==-1? -1:f[des];
}
int MaxFlow(int sce,int des)
{
int increasement=0;
int sumflow=0;
while((increasement=BFS(sce,des))!=-1)
{
int k=des;//利用前驱寻找路径
while(k!=sce)
{
int last=pre[k];
c[last][k]-=increasement;//改变正向边的容量
c[k][last]+=increasement;//改变反向边的容量
k=last;
}
sumflow+=increasement;
}
return sumflow;
}
int main()
{
ios_base::sync_with_stdio(false);
while(cin>>m>>n)
{
memset(c,0,sizeof(c));
memset(f,0,sizeof(f));
for(int i=1;i<=m;i++)
{
int st,ed,power;
cin>>st>>ed>>power;
c[st][ed]+=power;//输入的时候可能会有相同边不同的流量,所以这里最好用+=
}
int ans=MaxFlow(1,n);
cout<
2.dinic算法
HDU3549
邻接表写法
#include
#include
#include
#include
#include
#include
#include
#define memset(a,v) memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(1000);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
struct node
{
int to,next,cap;
node() {}
node(int to,int next,int cap):to(to),next(next),cap(cap) {}
} edge[2*MAXL+50];
int head[MAXL+50];
int level[MAXL+50];
int n,m,cnt;
int BFS(int sc,int st)
{
queue<int>q;
memset(level,0);
level[sc]=1;
q.push(sc);
while(!q.empty())
{
int u=q.front();
q.pop();
if(u==st)
return 1;
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to,c=edge[i].cap;
if(!level[v] && c)
level[v]=level[u]+1,q.push(v);
}
}
return 0;
}
int dfs(int sc,int st,int maxFlow)
{
if(sc==st)
return maxFlow;
int flow=0;
for(int i=head[sc]; ~i; i=edge[i].next)
{
int v=edge[i].to,c=edge[i].cap;
if(level[v]==level[sc]+1 && c>0)
{
flow=dfs(v,st,min(maxFlow,c));
if(flow)
{
edge[i].cap-=flow;
edge[i^1].cap+=flow;
return flow;
}
}
}
return 0;
}
int dinic(int sc,int st)
{
int ans=0;
while(BFS(sc,st))
ans+=dfs(sc,st,INF);
return ans;
}
void add_edge(int u,int v,int w)
{
edge[cnt]=node(v,head[u],w);
head[u]=cnt++;
}
void init()
{
cnt=0;
memset(head,-1);
}
int main()
{
int T;
scanf("%d",&T);
int CASE=1;
while(T--)
{
init();
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,0);
}
int ans=dinic(1,n);
cout<<"Case "<": ";
cout<
当前弧优化版本
#include
#include
#include
#include
#include
#include
#include
#define memset(a,v) memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(1000);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
struct node
{
int to,next,cap;
node() {}
node(int to,int next,int cap):to(to),next(next),cap(cap) {}
} edge[2*MAXL+50];
int head[MAXL+50];
int level[MAXL+50];
int current[MAXL+50];
int n,m,cnt;
int BFS(int sc,int st)
{
queue<int>q;
memset(level,0);
for(int i=0;i<=n;i++) current[i]=head[i];//初始化current数组
level[sc]=1;
q.push(sc);
while(!q.empty())
{
int u=q.front();
q.pop();
if(u==st)
return 1;
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to,c=edge[i].cap;
if(!level[v] && c)
level[v]=level[u]+1,q.push(v);
}
}
return 0;
}
int dfs(int sc,int st,int maxFlow)
{
if(sc==st)
return maxFlow;
int flow=0;
for(int i=current[sc]; ~i; i=edge[i].next)//当前弧优化
{
current[sc]=i;
int v=edge[i].to,c=edge[i].cap;
if(level[v]==level[sc]+1 && c>0)
{
flow=dfs(v,st,min(maxFlow,c));
if(flow)
{
edge[i].cap-=flow;
edge[i^1].cap+=flow;
return flow;
}
}
}
return 0;
}
int dinic(int sc,int st)
{
int ans=0;
while(BFS(sc,st))
ans+=dfs(sc,st,INF);
return ans;
}
void add_edge(int u,int v,int w)
{
edge[cnt]=node(v,head[u],w);
head[u]=cnt++;
}
void init()
{
cnt=0;
memset(head,-1);
}
int main()
{
int T;
scanf("%d",&T);
int CASE=1;
while(T--)
{
init();
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,0);
}
int ans=dinic(1,n);
cout<<"Case "<": ";
cout<
这几天做了一道HDU 3416 上面的代码卡时间了。
一直没找出原因,后来不停的debug之后发现是上面的dfs写的其实不好,递归次数可能不是最优的。
那么换一个:
int dfs(int u,int des,int increaseRoad)
{
if(u==des)
return increaseRoad;
int ret=0;
for(int k=head[u]; k!=-1; k=edge[k].next)
{
int v = edge[k].to,w=edge[k].cap;
if(level[v]==level[u]+1&&w!=0)
{
int MIN = min(increaseRoad-ret,w);
w = dfs(v,des,MIN);
if(w > 0)
{
edge[k].cap-=w;
edge[k^1].cap+=w;
ret+=w;
if(ret==increaseRoad)
return ret;
}
}
}
return ret;
}