网络流解决混合欧拉回路问题

网络流解决混合欧拉回路问题

解析

image.png

例题

欧拉回路,只不过图即存在有向边,又存在无向边,问是否存在欧拉回路

n点, m边的图,下面m条边。标准图论输入

下面代码中的路径第三个值为‘1’表示有向边,否则是双向边。

代码

#include <bits/stdc++.h>

using namespace std;

struct Dinic {

    static const int MAXN = 1050 + 7;
    static const int MAXM = MAXN * MAXN;
    static const int INF = 0x3f3f3f3f;

    int n, m, s, t;

    int first[MAXN], cur[MAXN], dist[MAXN], sign;

    struct Node {
        int to, flow, next;
    } edge[MAXM * 4];

    inline void init(int start, int vertex, int ss, int tt) {
        n = vertex, s = ss, t = tt;
        for(int i = start; i <= n; i++ ) {
            first[i] = -1;
        }
        sign = 0;
    }

    inline void add_edge(int u, int v, int flow) {
        edge[sign].to = v, edge[sign].flow = flow, edge[sign].next = first[u];
        first[u] = sign++;
        edge[sign].to = u, edge[sign].flow = 0, edge[sign].next = first[v];
        first[v] = sign++;
    }

    inline int dinic() {
        int max_flow = 0;
        while(bfs(s, t)) {
            for(int i = 0; i <= n; i++ ) {
                cur[i] = first[i];
            }
            max_flow += dfs(s, INF);
        }
        return max_flow;
    }

    bool bfs(int s, int t) {
        memset(dist, -1, sizeof(dist));
        queue<int>que;
        que.push(s), dist[s] = 0;
        while(!que.empty()) {
            int now = que.front();
            que.pop();
            if(now == t) {
                return 1;
            }
            for(int i = first[now]; ~i; i = edge[i].next) {
                int to = edge[i].to, flow = edge[i].flow;
                if(dist[to] == -1 && flow > 0) {
                    dist[to] = dist[now] + 1;
                    que.push(to);
                }
            }
        }
        return 0;
    }


    int dfs(int now, int max_flow) {
        if(now == t) {
            return max_flow;
        }
        int ans = 0, next_flow = 0;
        for(int &i = cur[now]; ~i; i = edge[i].next) {
            int to = edge[i].to, flow = edge[i].flow;
            if(dist[to] == dist[now] + 1 && flow > 0) {
                next_flow = dfs(to, min(max_flow - ans, flow));
                ans += next_flow;
                edge[i].flow -= next_flow;
                edge[i ^ 1].flow += next_flow;
                if(ans == max_flow) {
                    return max_flow;
                }

            }
        }
        if(ans == 0) {
            return dist[now] = 0;
        }
        return ans;
    }

} dinic;

const int MAXN = 1050;

int n, m;

int indeg[MAXN], outdeg[MAXN];

struct Input {
    int u, v, d;
} edge[MAXN];

int main()
{
    while(~scanf("%d %d", &n, &m)) {
        memset(indeg, 0, sizeof(indeg));
        memset(outdeg, 0, sizeof(outdeg));
        dinic.init(0, n + 1, 0, n + 1);
        for(int i = 1; i <= m; i++ ) {
            scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].d);
            indeg[ edge[i].v ]++;
            outdeg[ edge[i].u ]++;
            if(edge[i].d == 0) {
                dinic.add_edge(edge[i].u, edge[i].v, 1);
                dinic.add_edge(edge[i].v, edge[i].u, 1);
            }
        }
        bool ok = 1;
        int sum = 0;
        for(int i = 1; i <= n; i++) {
            int delta = abs(indeg[i] - outdeg[i]);
            if(delta % 2 == 1) {
                ok = 0;
                break;
            }
            if(indeg[i] > outdeg[i]) {
                dinic.add_edge(0, i, delta / 2);
                sum += delta / 2;
            } else {
                dinic.add_edge(i, n + 1, delta / 2);
            }
        }
        if(!ok) {
            puts("impossible");
            continue;
        }
        if(dinic.dinic() == sum) {
            puts("possible");
        } else {
            puts("impossible");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Q1143316492/p/9832459.html