zoukankan      html  css  js  c++  java
  • P3376 【模板】网络最大流

    EK算法  (个人感觉没有dinic好理解)

     1 //Edmonds-Karp算法
     2 //时间复杂度o(n*m*m)
     3 #include<iostream>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<queue>
     8 using namespace std;
     9 
    10 const int N=10005;
    11 const int M=100005;
    12 const int INF=599518803;
    13 
    14 int n,m,s,t;
    15 int num_edge,head[N];
    16 int val[N],pre[N];
    17 struct Edge
    18 {
    19     int u,v,w,flow,nxt;
    20 }edge[M<<1];
    21 
    22 int read()
    23 {
    24     int num=0;char c=getchar();
    25     for(;!isdigit(c);c=getchar());
    26     for(;isdigit(c);c=getchar())
    27         num=num*10+c-'0';
    28     return num;
    29 }
    30 
    31 void add_edge(int u,int v,int w)
    32 {
    33     edge[++num_edge].u=u;
    34     edge[num_edge].v=v;
    35     edge[num_edge].w=w;
    36     edge[num_edge].nxt=head[u];
    37     head[u]=num_edge;
    38 }
    39 
    40 bool bfs()
    41 {
    42     memset(val,0,sizeof(val));
    43     memset(pre,0,sizeof(pre));
    44     queue<int> que;
    45     val[s]=INF;//假设起点的可以的剩余流量无限大
    46     pre[s]=0;//储存上一个节点
    47     int now,v;
    48     que.push(s);
    49     while(!que.empty())
    50     {
    51         now=que.front(),que.pop();
    52         for(int i=head[now];i;i=edge[i].nxt)
    53         {
    54             v=edge[i].v;
    55             if(!val[v]&&edge[i].w>edge[i].flow)//如果没有经过并且容量大于流量
    56             {
    57                 que.push(v);
    58                 val[v]=min(val[now],edge[i].w-edge[i].flow);//剩余流量等于前一个节点的剩余流量与这条路的剩余流量的最小值
    59                 pre[v]=i;
    60             }
    61             if(val[t])//循环到了t就跳出循环
    62                 break;
    63         }
    64     }
    65     return val[t];
    66 }
    67 
    68 int main()
    69 {
    70     n=read(),m=read(),s=read(),t=read();
    71     num_edge=1;
    72     for(int i=1,u,v,w;i<=m;++i)
    73     {
    74         u=read(),v=read(),w=read();
    75         add_edge(u,v,w);
    76         add_edge(v,u,0);
    77     }
    78     int ans=0;
    79     while(bfs())
    80     {
    81         for(int i=t;i!=s;i=edge[pre[i]].u)
    82         {
    83             edge[pre[i]].flow+=val[t];
    84             edge[pre[i]^1].w-=val[t];
    85         }
    86         ans+=val[t];
    87     }
    88     printf("%lld",ans);
    89     return 0;
    90 }

    dinic详解blog:http://www.cnblogs.com/LUO77/p/6115057.html

    //Dinic
    //快忘干净了 
    //写一下自己能想起来的地 
    
    //改了几遍,差不多可以想起来了,而且也明白了一些以前没明白的地方 
    //emmm,在改进代码中加强对代码的理解程度吧算是 
    
    //开了氧气之后可以跑到72ms啦! 
    
    //要一开始让num_edge=1,感觉可能会因为忘写翻车 
    
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    const int N=1e4+5;
    const int M=1e5+5;
    
    int n,m,s,t;
    int head[N],from[N],num_edge;
    int dep[N];
    struct Edge
    {
        int v,flow,nxt;
    }edge[M<<1];
    
    inline int read()
    {
        char c=getchar();int num=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num;
    }
    
    inline void add_edge(int u,int v,int w)
    {
        edge[++num_edge].v=v;
        edge[num_edge].flow=w;
        edge[num_edge].nxt=head[u];
        head[u]=num_edge;
    }
    
    inline bool bfs()
    {
        for(int i=1;i<=n;++i)    //当前弧用到的 
            from[i]=head[i],dep[i]=0;
        queue<int> que;
        dep[s]=1,que.push(s);
        int now,v;
        while(!que.empty())
        {
            now=que.front(),que.pop();
            for(int i=head[now];i;i=edge[i].nxt)
            {
                v=edge[i].v;
                if(!dep[v]&&edge[i].flow)
                {
                    dep[v]=dep[now]+1;
                    if(v==t)    //到达汇点了,直接return 
                        return 1;
                    que.push(v);
                }
            }
        }
        return 0;
    }
    
    int dfs(int now,int flow)
    {
        if(now==t||!flow)
            return flow;
        int outflow=0,tmp;
        for(int &i=from[now],v;i;i=edge[i].nxt)        //只有满流之后才会换边,不满流不换边 
        {
            v=edge[i].v;
            if(dep[v]!=dep[now]+1)
                continue;
            tmp=dfs(v,min(flow,edge[i].flow));
            flow-=tmp;
            outflow+=tmp;    //又流出去了些流量 
            edge[i].flow-=tmp;    //当前边的流量- 
            edge[i^1].flow+=tmp;    //反向弧的流量+ 
            if(!flow)    //把从上边传下来的流量全都流完了,直接return,但是不要换边! 
                return outflow;
        }
        dep[now]=0;        //能从for循环里出来而没有提前return说明这个点所连出去的边流量全都流完了(全都满流),所以把这个点的dep设成0,他已经没有贡献了 
        return outflow;
    }
    
    int main()
    {
        n=read(),m=read(),s=read(),t=read();
        num_edge=1;
        for(int i=1,u,v,w;i<=m;++i)
        {
            u=read(),v=read(),w=read();
            add_edge(u,v,w);
            add_edge(v,u,0);
        }
        int ans=0;
        while(bfs())
            ans+=dfs(s,0x7fffffff);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    转Asktom:Pipelined Functions
    转:PVE法师附魔
    附魔300375图纸掉落大全
    转:Oracle直方图详解
    转:JSON的序列化及GET异步调用.
    转:ORACLE 中dbms_stats的使用
    jQuery中$.each的用法
    魔兽世界天赋详解之 法师篇 一冰法
    Miley's Oracle讲堂第三课:如何在Oracle中使用对象表存储数据.
    台服体验之急速升级
  • 原文地址:https://www.cnblogs.com/lovewhy/p/7846730.html
Copyright © 2011-2022 走看看