您的位置:首页 > 其它

HDU 3549 Flow Problem 解题报告(EK)算法

2012-08-12 00:56 393 查看
转载请注明出处:http://write.blog.csdn.net/postlist

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3549

这是一题裸的网络流题目。说有1000条边,可是只有十五个点,所以实际的边数最多只有15*15。EK复杂度O(VE2),5秒的时间、太多了!

可是,可是!! 就是这题搞的我很悲伤,几次TLE+WA+RE。。。。前天想到昨天近十二点,终于找到错误!

先贴上第一次错误代码

[cpp] view
plaincopy

#include<iostream>

#include<algorithm>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<queue>

#include<math.h>

#define MAXN 20

#define INF 1000

#define MIN(x,y) (x<y?x:y)

using namespace std;

int map[MAXN][MAXN];



int maxflow(int num,int map[][MAXN],int s,int t)

{

int flow[MAXN][MAXN],max_flow[MAXN],fa[MAXN],myqueue[MAXN];

int i,j,temp,qfront,qend,ans=0;

memset(flow,0,sizeof(flow));

while(1)

{

qfront=qend=0;

myqueue[qend++]=s;

fa[s]=-2;

max_flow[s]=INF;

memset(fa,-1,sizeof(fa));

while(qfront<qend)

{

temp=myqueue[qfront++];

for(i=0;i<num;i++) if(fa[i]==-1 && map[temp][i]>flow[temp][i])

{

fa[i]=temp;

myqueue[qend++]=i;

max_flow[i]=MIN(max_flow[temp],map[temp][i]-flow[temp][i]);

}

if(fa[t]!=-1)

{

int k=t;

while(fa[k]>=0)

{

flow[fa[k]][k]+=max_flow[t];//在这,应该加flow[k][fa[k]]-=max_flow[t];

k=fa[k];

}

break;

}

}

if(fa[t]==-1) return ans;

else ans+=max_flow[t];

}

}



int main()

{

int i,j,n,m,t,a,b,c;

scanf("%d",&t);

for(j=1;j<=t;j++)

{

memset(map,0,sizeof(map));

scanf("%d%d",&n,&m);

for(i=0;i<m;i++)

{

scanf("%d%d%d",&a,&b,&c);

map[a-1][b-1]+=c;

}

int ans=maxflow(n,map,0,n-1);

printf("Case %d: %d\n",j,ans);

}

return 0;

}

然后总结下错误原因:1、TLE:while(1)下面第四行,先赋值fa[s]=-2,再memset(fa,0,sizeof(fa));导致后面找到增广路后记录flow直接死循环(实在不知道为什么,求解)。
2、wa:记录flow时也应该记录相应的反向边!

下面贴上正解:

[cpp] view
plaincopy

#include<iostream>

#include<algorithm>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<queue>

#include<math.h>

#define MAXN 20

#define INF 1000

#define MIN(x,y) (x<y?x:y)

using namespace std;

int map[MAXN][MAXN];



int maxflow(int num,int map[][MAXN],int s,int t)

{

int flow[MAXN][MAXN],max_flow[MAXN],fa[MAXN],myqueue[MAXN];

int i,j,temp,qfront,qend,ans=0;

memset(flow,0,sizeof(flow));

while(1)

{

qfront=qend=0;

myqueue[qend++]=s;

max_flow[s]=INF;

memset(fa,-1,sizeof(fa));

fa[s]=-2;

while(qfront<qend)

{

temp=myqueue[qfront++];

for(i=0;i<num;i++) if(fa[i]==-1 && map[temp][i]>flow[temp][i])

{

fa[i]=temp;

myqueue[qend++]=i;

max_flow[i]=MIN(max_flow[temp],map[temp][i]-flow[temp][i]);

}

}

if(fa[t]!=-1)

{

int k=t;

while(fa[k]!=-2)

{

flow[fa[k]][k]+=max_flow[t];

flow[k][fa[k]]-=max_flow[t];

k=fa[k];

}

}

if(fa[t]==-1) return ans;

else ans+=max_flow[t];

}

}



int main()

{

int i,j,n,m,t,a,b,c;

scanf("%d",&t);

for(j=1;j<=t;j++)

{

memset(map,0,sizeof(map));

scanf("%d%d",&n,&m);

for(i=0;i<m;i++)

{

scanf("%d%d%d",&a,&b,&c);

map[a-1][b-1]+=c;

}

int ans=maxflow(n,map,0,n-1);

printf("Case %d: %d\n",j,ans);

}

return 0;

}

应该在宽搜后面加判断是否找到增广路。由于本题WA太久,第一次的AC我是用queue重新敲的。顺便贴上吧,时间差不多。都是一个算法:

[cpp] view
plaincopy

#include<iostream>

#include<algorithm>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<queue>

#include<math.h>

#define MAXN 20

#define INF 0x7fffffff

#define MIN(x,y) (x<y?x:y)

using namespace std;

int flow[MAXN][MAXN],map[MAXN][MAXN],fa[MAXN],a[MAXN];



int maxflow(int num,int map[][MAXN],int s,int t)

{

int ans=0;

memset(flow,0,sizeof(flow));

while(1)

{

queue<int> q;

q.push(s);

memset(a,0,sizeof(a));

a[s]=INF;

while(!q.empty())

{

int u=q.front(); q.pop();

for(int i=1;i<=num;i++) if(!a[i] && map[u][i]>flow[u][i])

{

fa[i]=u; q.push(i);

a[i]=MIN(a[u],map[u][i]-flow[u][i]);

}

}

if(a[t]==0) break;

for(int u=t;u!=s;u=fa[u])

{

flow[fa[u]][u]+=a[t];

flow[u][fa[u]]-=a[t];

}

ans+=a[t];

}

return ans;

}



int main()

{

int i,j,n,m,t,a,b,c;

scanf("%d",&t);

for(j=1;j<=t;j++)

{

memset(map,0,sizeof(map));

scanf("%d%d",&n,&m);

for(i=0;i<m;i++)

{

scanf("%d%d%d",&a,&b,&c);

map[a][b]+=c;

}

int ans=maxflow(n,map,1,n);

printf("Case %d: %d\n",j,ans);

}

return 0;

}

好了,网络流的诸多算法终于搞定一个,接下来 改进的SAP算法。。。时间不多,加油了cxb !
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: