题目链接
题目大意:
一个有v个顶点的完全图,找一条经过m条指定边的最短路径。
题目分析:
我们把原来的图看为未连接的,即每个点直接都无边。然后用给定的边连接,当我们画出这个图发现可能会有连通块。
我们的目的便是将所有的我们画出的边都走一边,而每个连通块都连接了所有的点,就代表要把连通块的每条边不重复走一遍。
所有本题就划分为了欧拉回路问题,现为每个连通块构造欧拉回路,所用的边数加上连接连通块之间所要的边数即为答案。
如何构造欧拉回路?只需要计算多少个奇点即可,因为奇点个数<=2才可以构成欧拉回路。
所有每个连通块,当奇点个数>=2,所需边数=(奇点-2)/2即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000+10;
int matrix[maxn][maxn], degree[maxn];
int v,e,w,ans;
void dfs(int u) {
for(int i = 1; i <= v; i++) {
if(matrix[u][i]) {
ans++;
degree[u]++, degree[i]++;
matrix[u][i] = matrix[i][u] = 0;
dfs(i);
}
}
}
int main() {
freopen("i.txt","r",stdin);
freopen("o.txt","w",stdout);
int Case = 1;
while(cin >> v >> e >> w ) {
if(!v && !e && !w) break;
int x,y;
ans = 0;
memset(matrix, 0, sizeof(matrix));
for(int i = 0; i < e; i++) {
cin >> x >> y;
matrix[x][y] = matrix[y][x] = 1;
}
for(int i = 1; i <= v; i++) {
for(int j = 1; j <= v; j++) {
if(matrix[i][j]) {
memset(degree, 0, sizeof(degree));
dfs(i);
int cnt = 0;
for(int i = 1; i <= v; i++)
if(degree[i]%2) cnt++;//计算奇点个数
if(cnt>=2) cnt-=2;
ans+=cnt/2;
ans++;
}
}
}
if(ans) ans--;
cout << "Case " << Case++ << ": " << ans*w << endl;
}
return 0;
}