【最大流 模板题 EdmondsKarp】HDU

来源:互联网 发布:淘宝装修模板复制 编辑:程序博客网 时间:2024/06/06 08:52

Problem Description

给你m,n分别代表m条边,n个点。接下来给你m条边,每条边u,v,w。u->v流量的容量为w。有重边

思路:模板题,所以给几个模板

EdmondsKarp-dfs-vector实现

//dfs实现#include<bits/stdc++.h>using namespace std;const int N = 1000;const int inf = 0x3f3f3f3f;struct node{    int to, cap, rev;//终点,容量,终点到起点的下标( a[temp.to][temp.rev].cap就代表反向边 )};vector<node> a[N];//用vector存图int vis[N];void add(int u, int v, int w)//存边{    a[u].push_back((node){v, w, a[v].size()});    a[v].push_back((node){u, 0, a[u].size() - 1});}int dfs(int s, int t, int f){    if(s == t) return f;//到达了终点返回    vis[s] = 1;//标记    for(int i = 0; i < a[s].size(); i++)    {        node &temp = a[s][i];//因为要改变图的边,所以取地址        if(!vis[temp.to] && temp.cap > 0)//没有走过的点,并且容量不为0        {            int d = dfs(temp.to, t, min(f, temp.cap));//d为限制流量。核心min(f, temp.cap);            if(d > 0)//回溯的过程中,如果d>0,代表找到了增广路            {                temp.cap -= d;//正向边 -d                a[temp.to][temp.rev].cap += d;//反向边 +d                return d;//继续回溯            }        }    }    return 0;}int max_flow(int s, int t){    int flow = 0;//最大流    for(;;){        memset(vis, 0, sizeof(vis));        int d = dfs(s, t, inf);//搜增广路,得到这条增广路上限制容量        if(d == 0) return flow;//如果为0代表搜不到,直接返回输出        flow += d;//搜到了,就叠加到最大流    }}int main(){    int n, m, u, v, w;    while(~scanf("%d %d", &m, &n))    {        memset(a, 0, sizeof(a));//初始化        while(m--)        {            scanf("%d %d %d", &u, &v, &w);            add(u, v, w);        }        printf("%d\n", max_flow(1, n));    }    return 0;}

EdmondsKarp-dfs-前向星实现

#include<bits/stdc++.h>using namespace std;#define mm 250struct node{    int to, w, next;};node Map[2 * mm];int vis[mm], head[mm];void add(int u, int v, int w, int &cnt){    Map[cnt].to = v;    Map[cnt].w = w;    Map[cnt].next = head[u];    head[u] = cnt++;    Map[cnt].to = u;    Map[cnt].w = 0;    Map[cnt].next = head[v];    head[v] = cnt++;}int dfs(int s, int t, int f){    vis[s] = 1;    if(s == t) return f;    for(int i = head[s]; ~i; i = Map[i].next)    {        int to = Map[i].to, &w = Map[i].w;        if(!vis[to] && w > 0)        {            int d = dfs(to, t, min(f, w));            if(d > 0)            {                w -= d;                Map[i^1].w += d;//反向边表达                //下标0是正向1就是反向。1^1=0,0^1=1;其他都和vector一致                return d;            }        }    }    return 0;}int EK(int s, int t)//求最大流{    int Max_flow = 0, d;    for(;;)    {        memset(vis, 0, sizeof(vis));        d = dfs(s, t, 0x3f3f3f3f);        if(d == 0) return Max_flow;//找不到增广路        Max_flow += d;    }}int main(){    int n, m, u, v, w;    while(~scanf("%d %d", &m, &n))    {        int cnt = 0;        memset(head, -1, sizeof(head));        while(m--)        {            scanf("%d %d %d", &u, &v, &w);//前向星            add(u, v, w, cnt);        }        printf("%d\n", EK(1, n));    }    return 0;}

EdmondsKarp-bfs实现

//BFS实现#include<bits/stdc++.h>using namespace std;const int N = 205;const int inf = 0x3f3f3f3f;int Map[N][N], Pre[N], Min_flow[N];//邻接矩阵存边,记录路径,记录限制流量int bfs(int s, int t){    memset(Pre, -1, sizeof(Pre));//初始化    queue<int> q;    Min_flow[s] = inf;//一开始限制流量是无穷    Pre[s] = 0;    q.push(s);    while(!q.empty())    {        s = q.front(); q.pop();        if(s == t) break;//到达终点、找到一条增广路;        for(int i = 1; i <= t; i++)        {            if(Pre[i] == -1 && Map[s][i] > 0)//没走过的点,容量大于0的点            {                //求限制流量                Min_flow[i] = min(Min_flow[s], Map[s][i]);                Pre[i] = s;//记录路径                q.push(i);//入队列            }        }    }    if(Pre[t] == -1) return -1;//代表没有找到增广路    else return Min_flow[t];//找到了返回限制流量}int Ek(int s, int t){    int Max_flow = 0, flow;//最大流,限制流量    while((flow = bfs(s, t)) != -1)//如果为-1代表搜不到增广路    {        Max_flow += flow;//更新最大流        int u = t;        while(u != 0)//增广路 路径上的边,正向-flow,反向+flow        {            Map[Pre[u]][u] -= flow;            Map[u][Pre[u]] += flow;            u = Pre[u];        }    }    return Max_flow;}int main(){    int m, u, v, w, n;    while(~scanf("%d %d", &m, &n))    {        memset(Map, 0, sizeof(Map));        while(m--)        {            scanf("%d %d %d", &u, &v, &w);            Map[u][v] += w; //有重边        }        printf("%d\n", Ek(1, n));    }    return 0;}
原创粉丝点击