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 !
题目链接: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 !
相关文章推荐
- HDU 3549 Flow Problem 解题报告(EK)算法
- HDU 3549 Flow Problem 解题报告(EK)算法
- HDU 3549 Flow Problem 网络最大流问题 EK、Dinic、ISAP三种算法
- hdu 2819 Swap 二分图匹配 匈牙利算法 解题报告
- hdu 3549 Flow Problem (最大流—EK—Dinic)
- HDU 3549 Flow Problem(最大流裸题,EK解法)
- HDU 3549 Flow Problem 网络流 EK
- hdu 3549 Flow Problem(最大流 EK,sap)
- HDU- 3549-Flow Problem (网络流之 EK)
- hdu 2063 过山车 二分图匹配 匈牙利算法 解题报告
- hdu 1532 POJ 1273 Drainage Ditches 和hdu 3549 Flow Problem 网络流入门(EK和dinic)
- HDU 3549 Flow Problem 最大流 最小增广路 EK算法 传说中的入门算法
- hdu 3549 Flow Problem(网络流增广路径主要算法)
- HDU 3549 Flow Problem【最大流入门题】【Ford-Fulkerson算法】【Dinic算法】【ISAP算法】
- 【最大流(EK)】hdu 3549 Flow Problem
- hdu 3549 Flow Problem(增广路算法)
- hdu 3549 Flow Problem(EK)
- hdu 3549 Flow Problem (EK 最大流)
- HDU 3294 解题报告 Manacher 算法
- hdu 1281 棋盘游戏 二分图匹配 匈牙利算法 解题报告