题目链接:Inspector’s Dilemma
题目大意:有完全图,给出E条必经的边,起点终点任选,经过每条边的代价一样,求最小代价。
解题思路:这道题可以转化成添加最少的边使最后的路径成为欧拉道路的问题,对于每个连通分量,如果奇度点大于2个则需要加边,两个连通分量之间也需要加边,求联通分量里点集的度数既可以用DFS也可以用BFS。
代码如下:
#include <set>
#include <stack>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
const int maxn = 2e4 + 15;
int n, m, w;
vector<int> G[1005];
int d[1005], vis[1005];
int final[1005];
void BFS(int s){
CLR(final);
queue<int> que;
que.push(s); vis[s] = 1;
final[s] = 1;
while(!que.empty()){
int u = que.front(); que.pop();
vis[u] = 1;
for(int v : G[u]){
if(!vis[v]){
if(!final[v]){
que.push(v);
final[v] = 1;
}
d[u]++; d[v]++;
}
}
}
return;
}
int main(){
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
int u, v, kase = 1;
while(cin >> n >> m >> w){
if(!n && !m && !w) break;
for(int i = 1; i <= n; i++) G[i].clear();
CLR(vis);
int ans = 0;
set<int> point;
for(int i = 1; i <= m; i++){
cin >> u >> v;
point.insert(u);
point.insert(v);
G[u].push_back(v);
G[v].push_back(u);
ans++;
}
for(int e : point){
if(vis[e]) continue;
ans++;
CLR(d);
BFS(e);
int deg = 0;
for(int j = 1; j <= n; j++){
if(d[j] & 1) deg++;
}
if(deg >= 2) deg -= 2;
ans += deg / 2;
}
if(ans) ans--;
cout << "Case " << kase << ": " << ans * w << endl;
kase++;
}
return 0;
}