`

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

阅读更多

转载请注明出处: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 plain copy
  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include<stdio.h>  
  4. #include<stdlib.h>  
  5. #include<string.h>  
  6. #include<queue>  
  7. #include<math.h>  
  8. #define MAXN 20  
  9. #define INF 1000  
  10. #define MIN(x,y) (x<y?x:y)  
  11. using namespace std;  
  12. int map[MAXN][MAXN];  
  13.   
  14. int maxflow(int num,int map[][MAXN],int s,int t)  
  15. {  
  16.     int flow[MAXN][MAXN],max_flow[MAXN],fa[MAXN],myqueue[MAXN];  
  17.     int i,j,temp,qfront,qend,ans=0;  
  18.     memset(flow,0,sizeof(flow));  
  19.     while(1)  
  20.     {  
  21.         qfront=qend=0;  
  22.         myqueue[qend++]=s;  
  23.         fa[s]=-2;  
  24.         max_flow[s]=INF;  
  25.         memset(fa,-1,sizeof(fa));  
  26.         while(qfront<qend)  
  27.         {  
  28.             temp=myqueue[qfront++];  
  29.             for(i=0;i<num;i++) if(fa[i]==-1 && map[temp][i]>flow[temp][i])  
  30.             {  
  31.                 fa[i]=temp;  
  32.                 myqueue[qend++]=i;  
  33.                 max_flow[i]=MIN(max_flow[temp],map[temp][i]-flow[temp][i]);  
  34.             }  
  35.             if(fa[t]!=-1)  
  36.             {  
  37.                 int k=t;  
  38.                 while(fa[k]>=0)  
  39.                 {  
  40.                     flow[fa[k]][k]+=max_flow[t];//在这,应该加flow[k][fa[k]]-=max_flow[t];  
  41.                     k=fa[k];  
  42.                 }  
  43.                 break;  
  44.             }  
  45.         }  
  46.         if(fa[t]==-1)  return ans;  
  47.         else ans+=max_flow[t];  
  48.     }  
  49. }  
  50.   
  51. int main()  
  52. {  
  53.     int i,j,n,m,t,a,b,c;  
  54.     scanf("%d",&t);  
  55.     for(j=1;j<=t;j++)  
  56.     {  
  57.         memset(map,0,sizeof(map));  
  58.         scanf("%d%d",&n,&m);  
  59.         for(i=0;i<m;i++)  
  60.         {  
  61.             scanf("%d%d%d",&a,&b,&c);  
  62.             map[a-1][b-1]+=c;  
  63.         }  
  64.         int ans=maxflow(n,map,0,n-1);  
  65.         printf("Case %d: %d\n",j,ans);  
  66.     }  
  67.     return 0;  
  68. }  



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



下面贴上正解:


[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include<stdio.h>  
  4. #include<stdlib.h>  
  5. #include<string.h>  
  6. #include<queue>  
  7. #include<math.h>  
  8. #define MAXN 20  
  9. #define INF 1000  
  10. #define MIN(x,y) (x<y?x:y)  
  11. using namespace std;  
  12. int map[MAXN][MAXN];  
  13.   
  14. int maxflow(int num,int map[][MAXN],int s,int t)  
  15. {  
  16.     int flow[MAXN][MAXN],max_flow[MAXN],fa[MAXN],myqueue[MAXN];  
  17.     int i,j,temp,qfront,qend,ans=0;  
  18.     memset(flow,0,sizeof(flow));  
  19.     while(1)  
  20.     {  
  21.         qfront=qend=0;  
  22.         myqueue[qend++]=s;  
  23.         max_flow[s]=INF;  
  24.         memset(fa,-1,sizeof(fa));  
  25.         fa[s]=-2;  
  26.         while(qfront<qend)  
  27.         {  
  28.             temp=myqueue[qfront++];  
  29.             for(i=0;i<num;i++) if(fa[i]==-1 && map[temp][i]>flow[temp][i])  
  30.             {  
  31.                 fa[i]=temp;  
  32.                 myqueue[qend++]=i;  
  33.                 max_flow[i]=MIN(max_flow[temp],map[temp][i]-flow[temp][i]);  
  34.             }  
  35.         }  
  36.         if(fa[t]!=-1)  
  37.         {  
  38.             int k=t;  
  39.             while(fa[k]!=-2)  
  40.             {  
  41.                 flow[fa[k]][k]+=max_flow[t];  
  42.                 flow[k][fa[k]]-=max_flow[t];  
  43.                 k=fa[k];  
  44.             }  
  45.         }  
  46.         if(fa[t]==-1)  return ans;  
  47.         else ans+=max_flow[t];  
  48.     }  
  49. }  
  50.   
  51. int main()  
  52. {  
  53.     int i,j,n,m,t,a,b,c;  
  54.     scanf("%d",&t);  
  55.     for(j=1;j<=t;j++)  
  56.     {  
  57.         memset(map,0,sizeof(map));  
  58.         scanf("%d%d",&n,&m);  
  59.         for(i=0;i<m;i++)  
  60.         {  
  61.             scanf("%d%d%d",&a,&b,&c);  
  62.             map[a-1][b-1]+=c;  
  63.         }  
  64.         int ans=maxflow(n,map,0,n-1);  
  65.         printf("Case %d: %d\n",j,ans);  
  66.     }  
  67.     return 0;  
  68. }  

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


[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include<stdio.h>  
  4. #include<stdlib.h>  
  5. #include<string.h>  
  6. #include<queue>  
  7. #include<math.h>  
  8. #define MAXN 20  
  9. #define INF  0x7fffffff  
  10. #define MIN(x,y) (x<y?x:y)  
  11. using namespace std;  
  12. int flow[MAXN][MAXN],map[MAXN][MAXN],fa[MAXN],a[MAXN];  
  13.   
  14. int maxflow(int num,int map[][MAXN],int s,int t)  
  15. {  
  16.     int ans=0;  
  17.     memset(flow,0,sizeof(flow));  
  18.     while(1)  
  19.     {  
  20.         queue<int> q;  
  21.         q.push(s);  
  22.         memset(a,0,sizeof(a));  
  23.         a[s]=INF;  
  24.         while(!q.empty())  
  25.         {  
  26.             int u=q.front(); q.pop();  
  27.             for(int i=1;i<=num;i++)  if(!a[i] && map[u][i]>flow[u][i])  
  28.             {  
  29.                 fa[i]=u; q.push(i);  
  30.                 a[i]=MIN(a[u],map[u][i]-flow[u][i]);  
  31.             }  
  32.         }  
  33.         if(a[t]==0) break;  
  34.         for(int u=t;u!=s;u=fa[u])  
  35.         {  
  36.             flow[fa[u]][u]+=a[t];  
  37.             flow[u][fa[u]]-=a[t];  
  38.         }  
  39.         ans+=a[t];  
  40.     }  
  41.     return ans;  
  42. }  
  43.   
  44. int main()  
  45. {  
  46.     int i,j,n,m,t,a,b,c;  
  47.     scanf("%d",&t);  
  48.     for(j=1;j<=t;j++)  
  49.     {  
  50.         memset(map,0,sizeof(map));  
  51.         scanf("%d%d",&n,&m);  
  52.         for(i=0;i<m;i++)  
  53.         {  
  54.             scanf("%d%d%d",&a,&b,&c);  
  55.             map[a][b]+=c;  
  56.         }  
  57.         int ans=maxflow(n,map,1,n);  
  58.         printf("Case %d: %d\n",j,ans);  
  59.     }  
  60.     return 0;  
  61. }  

好了,网络流的诸多算法终于搞定一个,接下来 改进的SAP算法。。。时间不多,加油了cxb  ! 更多详细信息请查看java教程网 http://www.itchm.com/forum-59-1.html
分享到:
评论

相关推荐

    ACM HDU 2000-2099 解题报告 杭电 ACM

    《ACM HDU 2000-2099 解题报告 杭电 ACM》是一份详尽的编程竞赛解题集,主要涵盖了杭电(Hangzhou Dianzi University)在线判题系统(HDU OJ)上的2000至2099号题目。这份解题报告是针对参与ACM/ICPC(国际大学生...

    HDU 1010-2500解题报告

    这个压缩包文件包含的是从HDU题目ID1010到2500之间的部分解题报告,对于想要提升编程能力、学习算法知识的ACMer来说,是一份宝贵的资源。 这些解题报告通常会包含以下几个方面的重要知识点: 1. **题目描述**:每...

    HDU+2000-2099+解题报告.zip

    《杭电OnlineJudge 2000-2099解题报告》是针对杭州电子科技大学(HDU)在线评测系统(OnlineJudge)中2000至2099题目的详细解答集锦,主要涵盖了算法分析、编程技巧以及问题解决策略等内容。这份解题报告以CHM...

    HDU 2000-2099 解题报告

    这份解题报告以CHM(Microsoft帮助文档格式)呈现,包含了从2000到2099号的HDU(杭州电子科技大学在线评测系统)题目,为学习和提升算法及编程技能提供了宝贵的资料。 HDU是国内外ACM/ICPC竞赛训练的重要平台之一,...

    HDU 1022 Train Problem I 附详细思路

    HDU 1022 Train Problem I 附详细思路

    hdu 3333 turing tree 解题报告

    题目“HDU 3333 Turing Tree”要求解决的问题是:给定一个整数序列和一系列区间,计算每个区间内不重复数字的和。由于数据规模较大(N ,000, K ,000),直接的暴力方法效率过低,因此我们需要采用一种更高效的数据...

    hdu1001解题报告

    hdu1001解题报告

    HDU 2000-2099 解题报告.CHM

    解题报告|ACM|程序设计参考程序以及题目的分析

    hdu2000~2099的解题报告

    【标题】"hdu2000~2099的解题报告"涉及的是一个针对杭州电子科技大学(HDU)ACM竞赛题目的解答集合,涵盖了从2000到2099共100道题目。这类解题报告通常包含了解决每一道问题的源代码,为学习算法和编程技巧提供了...

    hdu 母函数解题报告

    在这个解题报告中,我们看到两个具体的杭电(HDU)在线判题系统上的题目,它们都是关于使用1分、2分、5分硬币组合成不同金额的问题。 首先,我们来看第一个题目【hdu 2566】。这是一个典型的组合问题,题目要求找出...

    HDU+2000-2099+解题报告

    这个压缩包文件“HDU 2000-2099 解题报告”显然包含了在这个题号范围内的一些问题、答案以及解题思路,对于学习算法和提升编程能力具有很高的价值。 在这个范围内,我们可以预见到涵盖的算法类型可能包括但不限于:...

    100道 acm C语言 hdu 解题报告

    100道 acm C语言 hdu 解题报告

    hdu ACM代码 每种算法都有分类

    HDU ACM代码集合是针对ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest)的一份资源,这个压缩包中的代码涵盖了多种算法,是参赛者或对算法学习感兴趣的人宝贵的参考资料。ACM竞赛旨在...

    HDU算法讲解的PPT

    HDU算法讲解的PPT是一份非常有价值的教育资源,由知名教育机构HDU(杭州电子科技大学)的lcy老师精心制作并讲解。这份PPT涵盖了算法的各个方面,是学习和提升算法能力的理想材料。标签“算法”、“讲解”和“经典”...

    HDU1019(2028)解题报告

    Least Common Multiple ...先利用gcd算法求两个数的最大公约数,再考虑最小公倍数=两数乘积/最大公约数,即可求得最小公倍数。 注意:要考虑到输入的输入的n个数中的0,有0的要去掉0求其他数的最小公倍数。 代码:

    HDU2013暑期多校联合训练第一场0723-解题报告和标程

    【标题】"HDU2013暑期多校联合训练第一场0723-解题报告和标程"指的是2013年夏季,由杭州电子科技大学(HDU)主办的一场多学校参与的编程训练活动。这次训练是系列比赛的第一场,于7月23日举行,主要目的是提升参赛者...

    HDU杭电 计算机网络实验报告

    这份"HDU杭电 计算机网络实验报告"压缩包提供了丰富的实验材料,涵盖了多个关键的网络技术,包括交换机配置、路由协议、地址转换(NAT)、访问控制列表(ACL)以及动态主机配置协议(DHCP)等。以下是这些实验报告所...

    hdu1290解题报告

    ### hdu1290解题报告 #### 题目背景与意义 此题作为对杭州电子科技大学五十周年校庆的献礼,通过一道趣味性的数学问题来庆祝这一重要时刻。题目背景设置在一个充满想象力的情境下,即如何通过不同数量的切刀将一个...

    HDU解题报告,新手适用

    HDU解题报告,新手看看,高人也可以回顾下经典算法

    hdu动态规划算法集锦

    根据提供的信息,我们可以总结出以下关于“hdu动态规划算法集锦”的知识点: ### 动态规划基础概念 动态规划是一种解决多阶段决策问题的方法,它通过将原问题分解为互相重叠的子问题,利用子问题的解来构建原问题...

Global site tag (gtag.js) - Google Analytics