UVA12118 Inspector's Dilemma(欧拉路径)

题目:

某个国家有V(V≤1000)个城市,每两个城市之间都有一条双向道路直接相连,长度为T(每条边的长度都是T)。你的任务是找一条最短的道路(起点和终点任意),

使得该道路经过E条指定的边。输出这条道路的长度。

思路:

看完题目给出的两组数据,知道是一个欧拉路径的题目,然后考虑用并查集来统计连通分量的个数,然后答案就是这个个数减一+给出的边数E……

这题细思极恐,如果一个连通分量里边有多个奇点,那么这样只统计连通分量个数的做法就不对了。

这是一个无向连通图,那么对于每一个连通分量我们可以把它变成一个欧拉路径。再把所有的欧拉路径合成一个。

在合并的时候,每两个奇点可以用一条边来连接,除去最终留下的两个奇点,这样(奇点总数-2)/2-1+给出的边数就是答案。

对于是环的连通分量,可以默认他的奇点的个数是2.

如果给出的图只有一个点,那么答案一定是0.

代码:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define MAX 1000000009
#define FRE() freopen("in.txt","r",stdin)
#define FRO() freopen("out.txt","w",stdout)
using namespace std;
typedef long long ll;
const int maxn = 500010;
vector<int> mp[maxn];
int V,T,E;
int vis[maxn];

int DFS(int u){

    if(vis[u])
        return 0;
    //cout<<"GG:   "<<u<<endl;
    vis[u] = 1;
    int cnt=0;//奇点的个数
    if(mp[u].size()%2)
        cnt++;
    for(int i=0; i<mp[u].size(); i++){
        cnt += DFS(mp[u][i]);
    }
    return cnt;
}

int main(){
    //FRE();
    int cs = 0;
    ios::sync_with_stdio(false);
    while(cin>>V>>E>>T && V){
        for(int i=0; i<2*V; i++){
            mp[i].clear();
        }
        for(int i=0; i<E; i++){
            int st,en;
            cin>>st>>en;
            mp[st].push_back(en);
            mp[en].push_back(st);
        }
        memset(vis,0,sizeof(vis));
        int ans=0;
        for(int i=1; i<=V; i++){//统计图中一共有多少个奇点
            if(!vis[i] && mp[i].size()){
                ans += max(DFS(i),2);
                //cout<<ans<<endl;
            }
        }
        ans = max(0,(ans-2)/2)+E;//处理图中只有一个点的情况
        cout<<"Case "<<++cs<<": "<<ans*T<<endl;
    }
    return 0;
}

 

posted @ 2019-01-23 13:02  sykline  阅读(182)  评论(0编辑  收藏  举报