uva12118(不用dfs的方法!)

来源:互联网 发布:域名备案名称 编辑:程序博客网 时间:2024/05/21 02:51

网上的人多么坑啊,这个鬼题本来就不用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;//奇点个数可以等于2res+=((odd[i]+1)>>1);//位运算加快速度,并没有什么鬼用} printf("Case %d: %d\n",++now,e==0?0:(res-1+e)*t);//小心点!}}

PS:数据没有自环和重边,不用判...


1 0