您的位置:首页 > 其它

HDU 3018 Ant Trip

2014-10-15 16:51 316 查看
这个题目一开始看起来,感觉有点难,请原谅我水平低,呵呵。因为做这题时是欧拉回路专题,所以肯定用欧拉回路,于是自己就在想怎么才能用欧拉回路呢?一开始想用DFS搜索,一看不行,太麻烦,本来自己就懒,所以这招几秒钟之后就排除在外。于是就简单的画了几个节点的图,来寻找其中的关系。经过一些试验,我发现貌似所要走的次数只和图中度为奇数的结点的个数number有关。一开始我还对number分奇偶性讨论,可是后来发现没必要。整体思路出来之后就开始写。写完去提交,WA,呵呵,意料之中。于是又开始了悲催的找错误的历程。找寻了好久才发现,原来错在了并查集上,看来自己还是要对并查集更深入地理解理解一番了,呵呵。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N=100005;
int degree
,father
,deep
,number
;
int m,n;
//这里自己的并查集写的可能有所复杂了,例如deep数组可能就没必要开,对时间影响并不大,
//我看了别人写的,貌似很简单,不过并查集就这几个操作,我就当写写练练手吧。
void make_set()
{
for(int i=1;i<=n;i++)
{
father[i]=i;
deep[i]=0;
number[i]=0;
}
}
int find_father(int x)
{
if(x!=father[x])
father[x]=find_father(father[x]);
return father[x];
}
void merge(int x,int y)
{
int a=find_father(x);
int b=find_father(y);
if(a==b)
return;
if(deep[a]>deep[b])
father[b]=a;
else
{
if(deep[a]==deep[b])
deep[b]++;
father[a]=b;
}
}
int main()
{
int a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(degree,0,sizeof(degree));
make_set();
while(m--)
{
scanf("%d%d",&a,&b);
degree[a]++,degree[b]++;
merge(a,b);
}
vector<int> v;
for(int i=1;i<=n;i++)
{
//我就是坑在这句话上的,一开始自己是这样的:f=father[i],我想前面的并查集之后,
//i的父亲肯定是树的根结点,没想到真的错了,打错特错,害得我找了好久的错误,
//以后自己要当心了,呵呵!
int f=find_father(i);
if(f==i&°ree[i]!=0)
v.push_back(i);
if(degree[i]%2==1)
number[f]++;
}
int ans=0,len=v.size();
//这里要注意如果是欧拉环路的情况,这样ans直接加1就可以了
for(int i=0;i<len;i++)
{
int t=v.at(i);
if(number[t]==0)
ans++;
else
ans+=number[t]/2;
}
v.clear();
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: