zoukankan      html  css  js  c++  java
  • hdu 3549 Flow Problem Edmonds_Karp算法求解最大流

    Flow Problem

    题意:N个顶点M条边,(2 <= N <= 15, 0 <= M <= 1000)问从1到N的最大流量为多少?

    分析:直接使用Edmonds_Karp算法即可;下面是对增广路的一些理解和代码的解释;

    残量:容量-流量;

    增广:求出从源点到汇点的一条道路中所有残量的最小值d,把对应的所有边上的流量增加d,反向边(t->s)流量减少d(反向边的cap其实一直是0,只是flow为负了);

    技巧:这次的ins的标号是从0开始的,即tot++,之前我都是++tot;这样head初始化就变为-1了,不能再是0;这样是为了每条边和其反向边的编号是存在XOR关系;即每次找到一条道路后从t找回到s(所以要在边中加入from)对每条边及其反向边的残量变化;

    注意:同时增广路可达到所有边数的两倍;以及每次寻找路径的时候要把queue清空,否则MLE..

    Edmond_Karp算法BFS查找每次需要O(m)总时间复杂度为O(n*m2),不够快所以跑了218ms

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<stdlib.h>
    #include<time.h>
    #include<stack>
    #include<set>
    using namespace std;
    #define rep0(i,l,r) for(int i = (l);i < (r);i++)
    #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
    #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
    #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
    #define MS0(a) memset(a,0,sizeof(a))
    #define MS1(a) memset(a,-1,sizeof(a))
    #define inf 0x3f3f3f3f
    #define pb push_back
    template<typename T>
    void read1(T &m)
    {
        T x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        m = x*f;
    }
    template<typename T>
    void read2(T &a,T &b){read1(a);read1(b);}
    template<typename T>
    void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
    template<typename T>
    void out(T a)
    {
        if(a>9) out(a/10);
        putchar(a%10+'0');
    }
    const int M = 1000;
    const int N = 20;
    int head[M<<1],tot;
    struct edge{
        int from,to,cap,flow,Next;
    }e[M<<1];
    void ins(int u,int v,int cap,int flow)
    {
        e[tot].Next = head[u];
        e[tot].from = u;//为了t->s时由v推到u;
        e[tot].to = v;
        e[tot].cap = cap;
        e[tot].flow = flow;
        head[u] = tot++;
    }
    queue<int> q;
    int p[N];//记录路径中边的标号
    int a[N];//起点到i的可改进量
    int Edmonds_Karp(int s,int t)
    {
        int flow = 0;
        for(;;){
            MS0(a);
            while(!q.empty()) q.pop();
            a[s] = inf;
            q.push(s);
            while(!q.empty()){
                int u = q.front();q.pop();
                for(int id = head[u];~id;id = e[id].Next){
                    int v = e[id].to,c = e[id].cap,f = e[id].flow;
                    if(!a[v] && c > f){
                        p[v] = id;
                        a[v] = min(a[u],c - f);// ** 递推到a[v]
                        q.push(v);
                    }
                }
                if(a[t]) break;
            }
            if(!a[t]) break;
            for(int u = t;u != s;u = e[p[u]].from){
                e[p[u]].flow += a[t];
                e[p[u]^1].flow -= a[t];
            }
            flow += a[t];
        }
        return flow;
    }
    int main()
    {
        int n,T,kase = 1;
        read1(T);
        while(T--){
            int V,E;
            read2(V,E);
            MS1(head);tot = 0;
            rep0(i,0,E){
                int u,v,w;
                read3(u,v,w);
                ins(u,v,w,0);ins(v,u,0,0);
            }
            printf("Case %d: ",kase++);
            out(Edmonds_Karp(1,V));
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    【网络】【交换机】相关字符串处理
    python【telnet】使用
    【?】使用汇总
    【dbm】【功率】换算
    快速【kill进程】
    常用功能【时间log】
    python切换镜像源
    git报remote HTTP Basic Access denied错误的解决方法
    求取1到n的素数的数学思想——埃拉托斯特尼筛法
    MySQL count(*) 和 count(字段) 区别
  • 原文地址:https://www.cnblogs.com/hxer/p/5187231.html
Copyright © 2011-2022 走看看