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;
}
原文地址:https://www.cnblogs.com/lovewhy/p/7846730.html