UVa 12118 nspector's Dilemma (构造+DFS+欧拉回路)

题意:给定n个点,e条边和每条边的长度t,每两个点之间都有路相连,让你求一条最短的路经过这e条边。

析:刚开始想到要判连通,然后把相应的几块加起来,但是,第二个样例就不过,后来一想,那么有欧拉回路的还得加1啊。

又想每次再判一次是不是欧拉回路,怎么判又是问题,因为并不知道哪些是连在一块的,还得再查找,麻烦啊。。。。

后来上网看了一下题解,原来是要构造啊,也就是说把每个连通块都构造成一个欧拉回路,那么再减去端点的,就能完全连通了。

真是好方法,欧拉回路满足每个点的度都是偶数,也就是说如果不是偶数那么我们就人为的给加上一条,最后计算我们加了多少条,

然后再加上原来题目的e条,就是最后的条数。

代码如下:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;
const int maxn = 1000 + 10;
int t, n, e;
vector<int> G[maxn];
bool vis[maxn];

int dfs(int u){
    if(vis[u])  return 0;
    vis[u] = true;
    int ans = (G[u].size() & 1);
    for(int i = 0; i < G[u].size(); ++i)
        ans += dfs(G[u][i]);
    return ans;
}

int solve(){
    int ans = 0;
    for(int i = 1; i <= n; ++i)
        if(!G[i].empty() && !vis[i])
            ans += max(dfs(i), 2);
    return max((ans-2) / 2, 0) + e;
}

int main(){
//    freopen("in.txt", "r", stdin);
    int kase = 0;
    while(scanf("%d %d %d", &n, &e, &t) == 3){
        if(!n && !e && !t)  break;
        int u, v;
        for(int i = 1; i <= n; ++i)  G[i].clear();
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < e; ++i){
            scanf("%d %d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }

        printf("Case %d: %d
", ++kase, t * solve());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dwtfukgv/p/5577214.html