zoukankan      html  css  js  c++  java
  • UVA 12118 Inspector's Dilemma(检查员的难题)(欧拉回路)

    题意:有一个n个点的无向完全图,找一条最短路(起点终点任意),使得该道路经过E条指定的边。

    分析:

    1、因为要使走过的路最短,所以每个指定的边最好只走一遍,所以是欧拉道路。

    2、若当前连通的道路不是欧拉道路,最好的方法是通过加边使其成为欧拉道路。

    3、若该图连通,则度数为奇数的点的个数只会是偶数个(连通图性质)。

    4、欧拉道路只有两个度数为奇数的点,其他点度数均为偶数。

    5、使一个连通图变为欧拉道路,只需要在所有度数为奇数的点之间加边,若一个连通图度数为奇数的点有x个,则需要加边(x - 2) / 2。

    6、给定的边可能组成了几个连通图(并查集判断连通图个数),将各个连通图都变成欧拉道路后,再依次连接各欧拉道路,使整个图连通,依次连接各欧拉道路的加边数为欧拉道路总数-1。

    7、最后便忘了加上指定的E条边的长度。

    8、注意如果没有指定边,最短路长度为0。

    #pragma comment(linker, "/STACK:102400000, 102400000")
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cmath>
    #include<iostream>
    #include<sstream>
    #include<iterator>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    #include<deque>
    #include<queue>
    #include<list>
    #define Min(a, b) ((a < b) ? a : b)
    #define Max(a, b) ((a < b) ? b : a)
    typedef long long ll;
    typedef unsigned long long llu;
    const int INT_INF = 0x3f3f3f3f;
    const int INT_M_INF = 0x7f7f7f7f;
    const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
    const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
    const int dr[] = {0, 1};
    const int dc[] = {1, 0};
    const int MOD = 1e9 + 7;
    const double pi = acos(-1.0);
    const double eps = 1e-8;
    const int MAXN = 1000 + 10;
    const int MAXT = 500 + 10;
    using namespace std;
    int fa[MAXN];
    int V, E, T;
    int e[MAXN];
    set<int> v[MAXN];//每个点的度数
    set<int> cnt;
    void init(){
        for(int i = 1; i <= V; ++i){
            fa[i] = i;
            v[i].clear();
        }
        memset(e, 0, sizeof e);
        cnt.clear();
    }
    int Find(int v){
        return fa[v] = (fa[v] == v) ? v : Find(fa[v]);
    }
    int solve(){
        if(E == 0) return 0;//如果没有指定边,最短路长度为0
        for(int i = 1; i <= V; ++i){
           int len = v[i].size();
           if(len == 0) continue;
           int f = Find(i);
           cnt.insert(f);
           if(len & 1){
                ++e[f];
           }
        }
        int ans = 0;
        for(int i = 1; i <= V; ++i){
            if(e[i]){
                ans += (e[i] - 2) / 2;
            }
        }
        return (ans + (int)cnt.size() - 1 + E) * T;
    }
    int main(){
        int kase = 0;
        while(scanf("%d%d%d", &V, &E, &T) == 3){
            if(!V && !E && !T) return 0;
            init();
            for(int i = 0; i < E; ++i){
                int x, y;
                scanf("%d%d", &x, &y);
                v[x].insert(y);
                v[y].insert(x);
                int tx = Find(x);
                int ty = Find(y);
                if(tx < ty) fa[ty] = tx;
                else if(tx > ty) fa[tx] = ty;
            }
            printf("Case %d: %d\n", ++kase, solve());
        }
        return 0;
    }
  • 相关阅读:
    正则表达式
    模块的初始
    装饰器 1
    匿名函数
    内置函数一(待跟新)
    python 学习迭代器的认识
    python 学习笔记 —— 函数的认识
    搭建yum 源
    python 学习第六天 文件的处理方式
    python 学习第五天 字典得 增删改查
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/6298171.html
Copyright © 2011-2022 走看看