题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1532
题目给出源点和漏点,还有一些边,要求源与漏之间的最大流,我采用了Edmonds Karp算法,该算法是Ford-Fulkerson算法的一种实现,该算法的关键技术是残留网络和残留网络上的反向边,相当于给了搜索策略一个“反悔”的机会,算法的实行过程是每次都寻找一条源点到漏点的增广路径,算出流的大小,每次寻找到一条路径就进行累加直到无法寻找到一条增广路径。寻找增广路径的一般做法是bfs,用dfs的话迭代的次数可能会非常大,十分消耗速度。在Edmonds Karp算法中,一次增广路径的查找需要消耗O(|E|)的时间,在O(|V||E|)次增广之后最大流就能被找到,所以Edmonds Karp 算法的时间复杂度大约是O(|V||E|^2),复杂度在边多的情况下是非常高的,还有其他如Dinic、ISAP算法等最大流算法,本次我先自写一个EdmondsKarp算法。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define mp(a,b) make_pair((a),(b)) 17 #define P pair<int,int> 18 #define dbg(args) cout<<#args<<":"<<args<<endl; 19 #define inf 0x3f3f3f3f 20 const int maxn=1005; 21 int n,m,t; 22 inline int read(){ 23 int ans=0,w=1; 24 char ch=getchar(); 25 while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} 26 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); 27 return ans*w; 28 } 29 int g[maxn][maxn],pre[maxn];//这里的g数组不但保存了正向边的信息还保存了残留网络的信息 30 int bfs(int src,int sink) 31 { 32 int flow[maxn]; 33 mem(pre,-1); 34 flow[src]=inf;pre[src]=0;//每次从源点发出一股无穷大的水流 35 queue<int> q;q.push(src); 36 while(!q.empty()) 37 { 38 int u=q.front(); 39 q.pop(); 40 if(u==sink)break;//到达漏点 41 f(i,1,n) 42 { 43 if(i!=src&&pre[i]==-1&&g[u][i]>0)//找到一个不是源点而且没有访问过并且与当前点存在边的结点 44 { 45 pre[i]=u; 46 q.push(i); 47 flow[i]=min(flow[u],g[u][i]);//经过i点之后的源的大小更新成为边的大小或者是前驱结点的较小值 48 } 49 } 50 } 51 if(pre[sink]==-1)return -1;//漏点没有被搜索到 52 return flow[sink]; 53 } 54 int maxflow(int src,int sink) 55 { 56 int Maxflow=0; 57 while(1) 58 { 59 int flow=bfs(src,sink); 60 if(flow==-1)break; 61 int cur=sink;//从漏点开始,一步步向源点回退,更新残余网络 62 while(cur!=src) 63 { 64 int father=pre[cur]; 65 g[father][cur]-=flow;//从父结点到当前结点的路径上的流量减少flow 66 g[cur][father]+=flow;//从当前结点到父结点之间增加了一条残余流量 67 cur=father;//回溯更新参与网络 68 } 69 Maxflow+=flow; 70 } 71 return Maxflow; 72 } 73 int main() 74 { 75 //freopen("input.txt","r",stdin); 76 //freopen("output.txt","w",stdout); 77 std::ios::sync_with_stdio(false); 78 while(scanf("%d%d",&m,&n)!=EOF) 79 { 80 mem(g,0); 81 int u,v,w; 82 f(i,1,m) 83 { 84 u=read(),v=read(),w=read(); 85 g[u][v]+=w; 86 } 87 pf("%d ",maxflow(1,n)); 88 } 89 90 }