zoukankan      html  css  js  c++  java
  • The Chinese Postman Problem HIT

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

    无向图中国邮路问题:

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

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

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

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

    有向图的中国邮路问题:

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

    #include <iostream>
    #include <cstdio>
    #include <sstream>
    #include <cstring>
    #include <map>
    #include <cctype>
    #include <set>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #include <bitset>
    #define rap(i, a, n) for(int i=a; i<=n; i++)
    #define rep(i, a, n) for(int i=a; i<n; 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
    ", a);
    #define plld(a) printf("%lld
    ", a);
    #define pc(a) printf("%c
    ", a);
    #define ps(a) printf("%s
    ", a);
    #define MOD 2018
    #define LL long long
    #define ULL unsigned long long
    #define Pair pair<int, int>
    #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;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    POJ2778 DNA Sequence AC自动机上dp
    codeforces732F Tourist Reform 边双联通分量
    codeforces786B Legacy 线段树优化建图
    洛谷P3588 PUS 线段树优化建图
    codeforces1301D Time to Run 模拟
    codeforces1303B National Project 二分或直接计算
    codeforces1303C Perfect Keyboard 模拟或判断欧拉路
    codeforces1303D Fill The Bag 二进制应用+贪心
    python之路——使用python操作mysql数据库
    python之路——mysql索引原理
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9748775.html
Copyright © 2011-2022 走看看