高级算法设计——网络流问题

文章目录

  • 网络流问题HDU3549
    • EK算法求解
  • 最大流HDU1532
    • 法一、EK算法求解
    • 法二、Dinic算法求解
      • 如果喜欢我的文章,请记得三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持,下期更精彩!!!

网络流问题HDU3549

高级算法设计——网络流问题_第1张图片
高级算法设计——网络流问题_第2张图片

EK算法求解

详细C++代码如下:

#include
#include
#include
#include

using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 20;
const int M = 1005;
int cnt;
int head[N], pre[N];
bool vis[N];

struct Edge{
    int v, next;
    int cap, flow;
}E[M << 1];     //包含正向边和反向边

void init() {
    memset(head, -1, sizeof(head));
    cnt = 0;
}

void add(int u, int v, int c) {
    E[cnt].v = v;
    E[cnt].cap = c;
    E[cnt].flow = 0;
    E[cnt].next = head[u];      //头插法
    head[u] = cnt++;
}

bool bfs(int s, int t) {
    memset(pre, -1, sizeof(pre));
    memset(vis, 0, sizeof(vis));
    queue<int>q;
    vis[s] = 1;
    q.push(s);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(int i = head[u]; ~i; i= E[i].next) {
            int v = E[i].v;
            if(!vis[v] && E[i].cap > E[i].flow) {
                vis[v] = 1;
                pre[v] = i;     //边下标
                q.push(v);
                if(v == t) {
                    return 1;       //找到一条可增广路
                }
            }
        }
    }
    return 0;
}

int EK(int s, int t) {
    int maxflow = 0;
    while(bfs(s, t)) {
        int v = t, d = inf;
        while(v != s) {     //找可增量d
            int i = pre[v];
            d = min(d, E[i].cap - E[i].flow);
            v = E[i^1].v;
        }
        maxflow += d;
        v = t;
        while(v != s) {     //沿可增广路增流
            int i = pre[v];
            E[i].flow += d;
            E[i^1].flow -= d;
            v = E[i^1].v;
        }
    }
    return maxflow;
}

int main() {
    int T, n, m, u, v, w, cas = 1;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        init();
        for(int i = 1; i <= m; i++) {
            scanf("%d %d %d", &u, &v, &w);
            add(u, v, w);
            add(v, u, 0);
        }
        printf("Case %d: %d\n", cas++, EK(1, n));
    }
}

样例运行结果如下:
高级算法设计——网络流问题_第3张图片

最大流HDU1532

高级算法设计——网络流问题_第4张图片
高级算法设计——网络流问题_第5张图片
高级算法设计——网络流问题_第6张图片

法一、EK算法求解

详细C++代码如下:

#include
#include
#include
#include

using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 205;
const int M = 205;
int cnt;
int head[N], pre[N];
bool vis[N];

struct Edge{
    int v, next;
    int cap, flow;
}E[M<<1];     //包含正向边和反向边

void init() {
    memset(head, -1, sizeof(head));
    cnt = 0;
}

void add(int u, int v, int c) {
    E[cnt].v = v;
    E[cnt].cap = c;
    E[cnt].flow = 0;
    E[cnt].next = head[u];      //头插法
    head[u] = cnt++;
}

bool bfs(int s, int t) {
    memset(pre, -1, sizeof(pre));
    memset(vis, 0, sizeof(vis));
    queue<int>q;
    vis[s] = 1;
    q.push(s);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(int i = head[u]; ~i; i= E[i].next) {
            int v = E[i].v;
            if(!vis[v] && E[i].cap > E[i].flow) {
                vis[v] = 1;
                pre[v] = i;     //边下标
                q.push(v);
                if(v == t) {
                    return 1;       //找到一条可增广路
                }
            }
        }
    }
    return 0;
}

int EK(int s, int t) {
    int maxflow = 0;
    while(bfs(s, t)) {
        int v = t, d = inf;
        while(v != s) {     //找可增量d
            int i = pre[v];
            d = min(d, E[i].cap - E[i].flow);
            v = E[i^1].v;
        }
        maxflow += d;
        v = t;
        while(v != s) {     //沿可增广路增流
            int i = pre[v];
            E[i].flow += d;
            E[i^1].flow -= d;
            v = E[i^1].v;
        }
    }
    return maxflow;
}

int main() {
    int n, m, u, v, w;
    while(~scanf("%d %d", &m, &n)) {
        init();
        for(int i = 1; i <= m; i++) {
            scanf("%d %d %d", &u, &v, &w);
            add(u, v, w);
            add(v, u, 0);
        }
        printf("%d\n", EK(1, n));
    }
    return 0;
}

样例运行结果如下:
高级算法设计——网络流问题_第7张图片

法二、Dinic算法求解

详细C++代码如下:

#include
#include
#include
#include

using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 205;
const int M = 205;
int cnt;
int head[N], d[N];

struct Edge{
    int v, next;
    int cap, flow;
}E[M<<1];     //包含正向边和反向边

void init() {
    memset(head, -1, sizeof(head));
    cnt = 0;
}

void add(int u, int v, int c) {
    E[cnt].v = v;
    E[cnt].cap = c;
    E[cnt].flow = 0;
    E[cnt].next = head[u];      //头插法
    head[u] = cnt++;
}

bool bfs(int s, int t) {
    memset(d, 0, sizeof(d));
    queue<int>q;
    d[s] = 1;       //源点是第一层
    q.push(s);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(int i = head[u]; ~i; i= E[i].next) {
            int v = E[i].v;
            if(!d[v] && E[i].cap > E[i].flow) {
                d[v] = d[u] + 1;
                q.push(v);
                if(v == t) {
                    return 1;       //找到一条可增广路
                }
            }
        }
    }
    return 0;
}

int dfs(int u, int flow, int t) {
    if(u == t) {
        return flow;
    }
    int rest = flow;
    for(int i = head[u]; ~i && rest; i = E[i].next) {
        int v = E[i].v;
        if(d[v] == d[u] + 1 && E[i].cap > E[i].flow) {
            int k = dfs(v, min(rest, E[i].cap - E[i].flow), t);
            if(!k) {
                d[v] = 0;
            }
            E[i].flow += k;
            E[i^1].flow -= k;
            rest -= k;
        }
    }
    return flow - rest;
}

int Dinic(int s, int t) {
    int maxflow = 0;
    while(bfs(s, t)) {
        maxflow += dfs(s, inf, t);
    }
    return maxflow;
}

int main() {
    int n, m, u, v, w;
    while(~scanf("%d %d", &m, &n)) {
        init();
        for(int i = 1; i <= m; i++) {
            scanf("%d %d %d", &u, &v, &w);
            add(u, v, w);
            add(v, u, 0);
        }
        printf("%d\n", Dinic(1, n));
    }
    return 0;
}

样例运行结果如下:
高级算法设计——网络流问题_第8张图片

如果喜欢我的文章,请记得三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持,下期更精彩!!!

你可能感兴趣的:(算法和数据结构,Are,You,OKay,C/C++,算法,图论,c++)