传送机
题目描述
黄黄同学要到清华大学上学去了。
黄黄同学很喜欢清华大学的校园,每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄黄同学想每条路也只走一遍。我们一般人很可能对一些地图是办不到每条路走一遍且仅走一遍的,但是黄黄同学有个传送机,他可以任意地将一个人从一个路口传送到任意一个路口。
可是,每传送一次是需要耗费巨大的内力的,黄黄同学希望可以用最少的传送次数完成游遍校园,你能帮助他吗?
因为黄黄同学只是游历校园,于是我们可以认为黄黄同学可以从任意点开始,到任意点结束。
注意:不必经过所有的点。
黄黄同学很喜欢清华大学的校园,每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄黄同学想每条路也只走一遍。我们一般人很可能对一些地图是办不到每条路走一遍且仅走一遍的,但是黄黄同学有个传送机,他可以任意地将一个人从一个路口传送到任意一个路口。
可是,每传送一次是需要耗费巨大的内力的,黄黄同学希望可以用最少的传送次数完成游遍校园,你能帮助他吗?
因为黄黄同学只是游历校园,于是我们可以认为黄黄同学可以从任意点开始,到任意点结束。
注意:不必经过所有的点。
输入
输入第一行一个整数N,表示黄黄的校园里一共有多少路口。
第二行一个整数M,表示路口之间有M条路。
后面M行,每行两个整数a、b,表示a与b之间有一条路,且路是双向的。
第二行一个整数M,表示路口之间有M条路。
后面M行,每行两个整数a、b,表示a与b之间有一条路,且路是双向的。
输出
输出一行一个整数S,表示黄黄同学最少的传送次数。
样例输入 Copy
3
2
1 2
2 3
样例输出 Copy
0
提示
对于100%的数据满足:N<=100000,M<=500000,1<=a,b<=N。
这里主要记录下自己的思维的错误之处。这个题是问补几条边成为一个欧拉通路。第一次想的做法是统计奇度数点的个数然后-1/2输出。在一些样例里没有问题。
但这忽略了,两个欧拉通路不连通也需要额外一条边来进行连。这也是本题并查集的应用之处
查看代码
#include<iostream>
#pragma GCC optimize(2)
using namespace std;
int n,m,ans;
int ver[1000001],f[1000001],a[1000001];
int fin(int x)
{
if(f[x]==x)return x;
return f[x]=fin(f[x]);
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)f[i]=i;
while(m--)
{
int x,y;
cin>>x>>y;
ver[x]++;
ver[y]++;
int a=fin(x),b=fin(y);
if(a!=b)f[b]=a;
}
for(int i=1;i<=n;i++)
if(ver[i]%2)
a[fin(i)]++;
for(int i=1;i<=n;i++)
if(ver[i]>0&&fin(i)==i)
ans=ans+1+max(0,(a[i]-2)/2);
ans--;//第一个进入不需要传送
if(ans<0)ans=0;//如果没有路传送次数为0
cout<<ans;
return 0;
}
作者:qbning
-------------------------------------------
个性签名:曾经的我们空有一颗望海的心,却从没为前往大海做过真正的努力
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!