任意两点之间都有连通,要输出经过所有给出的边的最小时间
要使经过所有所给边的时间最小,一定不会将一个边走过两次,这样就变成
了构造一个欧拉道路的问题,输入也许有多个连通块,所以每个连通块都要
构造成一个欧拉道路(回路),通过度数统计需要增加的边,再加上连接不同
连通快的边,再加上所给出的边就是答案。
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 1000 + 5;
int G[maxn][maxn];
int degree[maxn];
bool done[maxn];
int V, E, T;
vector<int> node;
int cnt, first;
void DFS(int u)
{
done[u] = true;
node.push_back(u);
for (int i = 1; i <= V; i++)
{
if (G[u][i])
{
if (first) //独点不计入连通块
{
cnt++;
first = 0;
}
degree[u]++;
if (!done[i])
DFS(i);
}
}
}
int main()
{
int t = 0;
while (cin >> V >> E >> T && V)
{
memset(G,0,sizeof(G));
memset(done, 0, sizeof(done));
memset(degree, 0, sizeof(degree));
int a, b;
for (int i = 0; i < E; i++)
{
cin >> a >> b;
G[a][b] = 1;
G[b][a] = 1;
}
cnt = 0;
int ans = 0;
int temp;
for (int i = 1; i <= V; i++)
if (!done[i])
{
first = 1; //独点不计入连通块
temp = 0;
node.clear();
DFS(i);
//cnt++;//独点不计入连通块
for (int i = 0; i < node.size(); i++)
if (degree[node[i]] % 2 == 1)
temp++;
if(temp) //temp==0代表首尾相连
ans += (temp - 2) / 2; //补边
}
if (cnt != 0) //注意零输入
ans += (cnt - 1) + E; //连接连通块
else
ans = 0;
cout << "Case " << ++t << ": " << ans*T << endl;
}
}