描述
zyc從小就比較喜歡玩一些小游戲,其中就包括畫一筆畫,他想請你幫他寫一個程序,判斷一個圖是否能夠用一筆畫下來。
規定,所有的邊都只能畫一次,不能重復畫。
-
輸入
第一行只有一個正整數N(N<=10)表示測試數據的組數。每組測試數據的第一行有兩個正整數P,Q(P<=1000,Q<=2000),分別表示這個畫中有多少個頂點和多少條連線。(點的編號從1到P)隨后的Q行,每行有兩個正整數A,B(0<A,B<P),表示編號為A和B的兩點之間有連線。
-
輸出
如果存在符合條件的連線,則輸出"Yes",如果不存在符合條件的連線,輸出"No"。
-
樣例輸入
2
4 3
1 2
1 3
1 4
4 5
1 2
2 3
1 3
1 4
3 4
- 樣例輸出
No
Yes
分析
歐拉定理 如果一個網絡是連通的並且奇頂點的個數等於0或2,那么它可以一筆畫出;否則它不可以一筆畫出。
判斷一筆畫的方法:
①是連通的。一個圖,如果圖上任意二點總有線段連接着,就稱為連通的。不是連通的就不能一筆畫出。
②奇點個數是0或者是2。圖上線段的端點可以分成二類,奇點和偶數。一個點,以它為端點的線段數是奇數就稱為奇點,線段數是偶數就稱為偶點。
一個圖是否是一筆畫就看奇點的個數,奇點個數是 0 或者 2,就是一筆畫,否則就不是一筆畫。
所以這個問題完全可以轉化策略為:
第一步: 首先我們不管它三七二十幾,先進行連通性的判斷。
第二步:
(1)如果是連通的,我們來判斷此圖的度的奇點的個數是0或者是2 ,如果是,則說明這個是歐拉圖,即可以一筆畫出,反之則不能一筆畫出
(2)如果是非連通的,這說明這個圖很定不能一筆畫出。
#include<bits/stdc++.h>
#define maxv 1001
using namespace std;
int p,q;
int vest[maxv];
int du[maxv];
void init(int n)
{
for(int i=0;i<=n;i++ )
vest[i]=i;
memset(du,0,sizeof(du));
}
int findx(int t)
{
if(vest[t]==t)return t;
return vest[t]=findx(vest[t]);
}
void mergex(int a,int b)
{
int x=findx(a);
int y=findx(b);
if(x!=y)
vest[x]=y;
}
int main()
{
//freopen("2.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&p,&q);
init(q);
for(int i=0; i<q; i++)
{
int a,b;
scanf("%d%d",&a,&b);
du[a]++;
du[b]++;
mergex(a,b);
}
int sum1=0;
for(int i=1;i<=p;i++)
{
if(vest[i]==i)
sum1++;
if(sum1>=2)break;
}
if(sum1>=2)
{
printf("No\n");
}
else
{
int sum2=0;
for(int i=1;i<=p;i++)
if(du[i]%2==1)
{
sum2++;
}
if(sum2==0||sum2==2)
printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
