The Chinese Postman Problem HIT - 2739(有向图中国邮路问题)

无向图的问题,如果每个点的度数为偶数,则就是欧拉回路,而对于一个点只有两种情况,奇数和偶数,那么就把都为奇数的一对点  连一条  边权为原图中这两点最短路的值  的边  是不是就好了

无向图中国邮路问题:

The Chinese Postman Problem HIT - 2739(有向图中国邮路问题)_第1张图片

 

 

 

有向图的问题,如果每个点的入度和出度相同,则就是欧拉回路,而这个情况就多了,相同、入度少一、入度少俩·····、出度少1、出度少俩,

呐 如果我们把入度少的 和 出度少的连起来是不是就是欧拉回路了,比如说点x的出度为7,入度为3;点y的出度为2,入度为4;点z的出度为2,入度为4;

那么x是连点y还是点z,当然是先连距离最小的那个,假设是y,那么x <- y 连两条边之后,x入度为7,入度为5,y的入度和出度相同,

那么x就开始连z,仔细想一想 这是不是就是费用流,先使路的费用小的满流,然后次小,然后次次小,所以费用流可以完美解决这个问题

有向图的中国邮路问题:

The Chinese Postman Problem HIT - 2739(有向图中国邮路问题)_第2张图片

 

 

咳咳。。。反正wrong  交网上的代码也wrong

#include 
#include 
#include 
#include 
#include 
#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define pd(a) printf("%d\n", a);
#define plld(a) printf("%lld\n", a);
#define pc(a) printf("%c\n", a);
#define ps(a) printf("%s\n", a);
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 30010, INF = 0x7fffffff, LL_INF = 0x7fffffffffffffff;
int n, m, s, t;
int head[maxn], d[maxn], vis[maxn], p[maxn], f[maxn], fi[maxn];
int in[maxn], out[maxn];
int cnt, flow, value;

struct node
{
    int u, v, c, w, next;
}Node[maxn << 1];

void add(int u, int v, int c, int w)
{
    Node[cnt].u = u;
    Node[cnt].v = v;
    Node[cnt].w = w;
    Node[cnt].c = c;
    Node[cnt].next = head[u];
    head[u] = cnt++;
}

int spfa()
{
    queue<int> Q;
    mem(vis, 0);
    mem(p, -1);
    for(int i = 0; i < maxn; i++) d[i] = INF;
    Q.push(s);
    d[s] = 0;
    vis[s] = 1;
    p[s] = 0, f[s] = INF;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        vis[u] = 0;
        for(int i = head[u]; i != -1; i = Node[i].next)
        {
            node e = Node[i];
            if(d[e.v] > d[u] + e.w && e.c > 0)
            {
                d[e.v] = d[u] + e.w;
                p[e.v] = i;
                f[e.v] = min(f[u], e.c);
                if(!vis[e.v])
                {
                    Q.push(e.v);
                    vis[e.v] = 1;
                }
            }
        }
    }
    if(p[t] == -1) return 0;
    flow += f[t]; value += f[t] * d[t];
    for(int i = t; i != s; i = Node[p[i]].u)
    {
        Node[p[i]].c -= f[t];
        Node[p[i]^1].c += f[t];
    }
    return 1;
}

void max_flow()
{
    while(spfa());
}

void init()
{
    mem(head, -1);
    mem(in, 0);
    mem(out, 0);
    cnt = value = flow = 0;
}

int find(int x)
{
    return fi[x] == x ? fi[x] : (fi[x] = find(fi[x]));
}


int main()
{
    int T;
    int u, v, w;
    cin >> T;
    while(T--)
    {
        for(int i = 0; i < maxn; i++) fi[i] = i;
        int flag = 0, ans = 0;
        init();
        int edge_sum = 0;
        cin >> n >> m;
        s = n + 1, t = n + 2;
        for(int i = 0; i < m; i++)
        {
            cin >> u >> v >> w;
            int l = find(u);
            int r = find(v);
            if(l != r) fi[l] = r;
            edge_sum += w;
            add(u, v, INF, w);
            in[v]++;
            out[u]++;
        }
        for(int i = 0; i < n; i++)
            if(fi[i] == i) ans++;
        if(ans > 1)
        {
            puts("-1");
            continue;
        }
        int tot_flow = 0;
        for(int i = 0; i < n; i++)
        {
            if(in[i] == 0 && out[i] == 0)
            {
                flag = 1;
                break;
            }
            if(out[i] > in[i]) add(i, t, out[i] - in[i], 0), tot_flow += out[i] - in[i];
            else if(in[i] > out[i]) add(s, i, in[i] - out[i], 0);
        }
        if(flag)
        {
            puts("-1");
            continue;
        }

        max_flow();
        if(tot_flow != flow)
        {
            puts("-1");
            continue;
        }
        cout << edge_sum + value << endl;
    }

    return 0;
}

 

转载于:https://www.cnblogs.com/WTSRUVF/p/9748775.html

你可能感兴趣的:(The Chinese Postman Problem HIT - 2739(有向图中国邮路问题))