POJ-1273 Drainage Ditches (最大流模板)

这题是看人家讲解最大流EK算法讲解然后慢慢对着模板敲出来的 = = 。
妈耶,看了半天总算是看懂什么是最大流了= =
麻麻我要回家,图论真难学。。。。。
emmmmm…..下面是代码的模板,然后加上我对这算法模板的一些理解和注释
(前提是要会用 == )
还是说下题意吧,,,
就是给你m个点,n条边,然后组成了个图,让你求这个图的最大流是多少。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<string>
/* 最大流 Ek算法
复杂度: O(n*m^2)
适合稀疏图, 不适合稠密图
*/

using namespace std;
 const int maxn = 220 ;
 const int INF = 0x7f7f7f7f;
int G[maxn][maxn] , flow[maxn] , pre[maxn] ; /// G 存图 ,flow描述从原点到当前点的容量 , pre标记上一步的曾广路是哪一条链
int n , m ;  /// 这道题 m 为点 , n 为边
queue<int> q;
 int BFS(int s , int t){  /// 作用是找曾广路
       while(!q.empty()) q.pop() ;
       memset(pre , -1 , sizeof(pre)) ;
       pre[s] = 0 ; flow[s] = INF ;
       q.push(s) ;
       while(!q.empty()){
        int  p = q.front() ;
        q.pop() ;
        if(p == t) break ; //走到了汇点

        for(int u = 1 ; u <= n ; u++){
            if(u!= s && G[p][u] >0 && pre[u] == -1) {
                pre[u] = p ;
                flow[u] = min(flow[p] , G[p][u]) ; ///当前节点上一段的流量和下一段的流量的最小值
                q.push(u)  ;
            }
        }
       }
       if(pre[t] == -1 ) return -1 ;
       return flow[t] ;  /// 返回曾广路径中的流量最小值
 }
 int EK(int s , int t){  /// 传入源点和汇点
   int delta = 0 , tot = 0 ;///tot记录最大流的值是多少 , delta记录这个图的曾广路的流量
   while(1){
    delta = BFS(s , t) ;/// 这里就是反复的对这个图BFS找曾广路,直到找不到为止
    if(delta == -1) break ;
    int p = t ;   /// 从曾广路开始往后退
    while(p != s){
        G[pre[p]][p] -= delta ;  ///正向边减去流量
        G[p][pre[p]] += delta ;  ///反向边加上
        p = pre[p] ;
    }
    tot += delta ;
   }
   return tot ;
 }

int main(){
int u , v ,w  ;
 while(scanf("%d%d",&m,&n) != EOF){
     memset(G , 0 , sizeof(G)) ;
     memset(flow , 0 , sizeof(flow)) ;
    for(int i = 0 ; i <m ; i++){
        scanf("%d%d%d",&u,&v,&w) ;
        G[u][v] += w ;  /// 这里是构图,如果有重边的话就相当于累加它的容量
    }
    printf("%d\n",EK(1 , n ) ) ;
 }
}
/*
自测样例:
6 5
1 2 6
1 3 7
1 4 8
2 5 10
3 5 10
4 5 10
21
5 4
1 2 8
2 4 10
2 3 100
3 4 2
1 3 7
10
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值