ICPC 训练联盟周赛-UCF Local Programming Contest 2018(Practice)

 

 此题明显要求欧拉通路的条数:鉴于无向图可能不是连通图,需要求出每个连通块的欧拉通路。每个块的欧拉通路求法是根据奇度顶点的个数判断。d==0||d==2则存在一条欧拉回路或欧拉通路。否则有d/2条欧拉通路。但是要特判一个仅有一个顶点的连通块,此情况不存在欧拉通路。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <cstdio>
#include <string>
#include <stack>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
typedef long long ll;
int d[200010];//d[i]=n;表示i号顶点的度为n
int du[200010];//du[cnt]=n;表示块号为cnt的连通块有奇度顶点n个
int f[200010];//f[i];i号顶点的根节点
int c[200010];//c[i]=x;表示i号顶点在块号x中
int cnt=0;//连通块号
int find(int x){
	int r=x;
	while(r!=f[r]){
		r=f[r];
	}
	int j=x;
	while(f[j]!=r){
		f[j]=r;
		j=f[x];
		x=j;
	}
	return r;
}
int main()
{
	IOS;
	int n,m,x,y;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		f[i]=i;
	}
	//并查集
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		d[x]++;d[y]++;
		int tx=find(x);
		int ty=find(y);
		if(tx!=ty){
			if(tx<ty)f[ty]=tx;
			else f[tx]=ty;
		}
	}
	for(int i=1;i<=n;i++){
		if(find(i)==i){
			if(d[i]==0)continue;
			c[i]=cnt++;//对连通块号离散化
		}
		du[c[f[i]]]+=d[i]&1?1:0;//对i号点所在的块的奇度顶点统计
	}
	ll ans=0;
	for(int i=0;i<cnt;i++){//遍历每一个块
		if(du[i]==0||du[i]==2)ans+=1;//存在一条欧拉通路
		else ans+=du[i]/2;//存在du[i]/2条欧拉通路
	}
	if(ans==1)cout<<"YES"<<endl;
	else {
		cout<<"NO"<<endl;
		cout<<ans<<endl;
	}
	getchar();
	getchar();
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章