网上的人多么坑啊,这个鬼题本来就不用dfs
第一步 直接用并查集找连通块!
第二步 然后就想办法让每个连通块变成欧拉道路:
1.每个连通块里面找奇点个数
2.每个连通块里面奇点两两配对(由于是欧拉道路,只需让奇点个数<=2)
第三步 让各个连通块连起来
就是连n-1条边!(n是连通块的个数)
(你可以画个图,就发现现在的连通块一定可以只用n-1条边连在一起)
第四步 把答案输出来
【注意:E的范围是E>=0,就是当E==0时输出0(我就死在这里)】
#include<bits/stdc++.h>
using namespace std;
typedef set<int>::iterator set_it;
const int maxn=1000+10;
int f[maxn],v,e,t,E;
int sum[maxn],res,now;
int degree[maxn],odd[maxn];
set<int>point;//存不同的点,免得重复枚举
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
void uni(int x,int y){
int _x=find(x);
int _y=find(y);
if(_x!=_y)f[_x]=_y;
}
int main(){
while(scanf("%d%d%d",&v,&e,&t)==3){
int E=e;
if(!v&&!e&&!t)break;
point.clear();res=0;
memset(sum,0,sizeof(sum));
memset(G,0,sizeof(G));
memset(degree,0,sizeof(degree));
memset(odd,0,sizeof(odd));
for(int i=1;i<=v;++i)f[i]=i;
for(int i=1,a,b;i<=e;++i){
scanf("%d%d",&a,&b);
if(a==b)continue;
uni(a,b);
degree[a]++;
degree[b]++;
point.insert(a);
point.insert(b);
} for(set_it it=point.begin();it!=point.end();++it){
if(degree[*it]%2)odd[find(*it)]++;
sum[find(*it)]=true;//找连通块个数和奇点个数
} for(int i=1;i<=v;++i)if(sum[i]){
res++; //统计
if(odd[i]<=1)continue;
if(odd[i]>=2)odd[i]-=2;//奇点个数可以等于2
res+=((odd[i]+1)>>1);//位运算加快速度,并没有什么鬼用
} printf("Case %d: %d\n",++now,e==0?0:(res-1+e)*t);//小心点!
}
}
PS:数据没有自环和重边,不用判...