题目大意:一个有v个顶点的完全图,找一条经过m条指定边的最短路径。
题目分析:当每条边仅经过一次时,路径最短。给出的边可能构成若干棵树。在一棵树中,奇点个数总为偶数,若一棵树的奇点个数为0,则这棵树可以构成欧拉回路,若不为0,则必有走不到的边(每条边仅经过一次,下同)。在一棵树中,设奇点个数为n,则走不到的边数为(n-2)/2 (n-2为除去起点和终点的奇点个数),这意味着,还需要走额外的(n-2)/2条边才能将这(n-2)/2条指定的但走不到的边走完。并且,这(n-2)/2条走不到的边是不共点的,这意味着,一棵树还是多棵树是无关紧要的。但是,如果有的树中奇点个数恰为0,没有走不到的边,此时这棵树成了孤立的了,要注意这种情况。
代码如下:
# include<iostream>
# include<cstdio>
# include<set>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;
struct Edge
{
int to,nxt;
};
Edge e[500000];
int n,m,t,head[1005],vis[1005],cnt,du[1005],num;
set<int>s;
void add(int u,int v)
{
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
void dfs(int u)
{
num+=(du[u]&1);
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].to;
if(!vis[v]){
vis[v]=1;
dfs(v);
}
}
}
int main()
{
int a,b,cas=0;
while(scanf("%d%d%d",&n,&m,&t)&&(n+m+t))
{
cnt=0;
s.clear();
memset(head,-1,sizeof(head));
memset(du,0,sizeof(du));
for(int i=0;i<m;++i)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
s.insert(a);
s.insert(b);
++du[a],++du[b];
}
num=0;
memset(vis,0,sizeof(vis));
for(set<int>::iterator it=s.begin();it!=s.end();++it){
if(!vis[*it]){
int temp=num;
vis[*it]=1;
dfs(*it);
if(temp+2>num)///注意树中奇点个数为0的情况
num=temp+2;
}
}
printf("Case %d: %d\n",++cas,(max(0,(num-2)/2)+m)*t);
}
return 0;
}