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;
}

 

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