虚虚实实
题意:
算卦先生来问你,对于每个他给出的无向图,是否存在一条路径能够经过所有边恰好一次,并且经过所有点?不需要满足最后回到起点。 (欧拉通路+欧拉图)
输入:
第一行一个数 T,表示有 T 组数据。对与每组数据,第一行有两个数 n,m,接下去 m 行每行两个数 u,v 描述一条无向边 (u,v)。图不保证联通。
输出:
对于每组数据,如果存在,输出"Zhen" ,否则输出 “Xun” 。
示例1
输入
2
2 2
1 1
2 1
4 6
1 3
1 4
1 2
3 2
4 2
4 3
输出
Zhen
Xun
备注:
1.1≤T≤200
2.2≤n≤30
1≤m≤ n(n−1)/2
欧拉通图:图中每条边且只通过一次,并且经过每一顶点的通路(首尾不相接)
欧拉图:图中每条边且只通过一次,并且经过每一顶点的回路(首尾相接)
无向图是否具有欧拉通路/回路的判定:
欧拉通路:图联通,图中只有俩个度为奇数的顶点(欧拉通路的俩个端点)
欧拉回路:图联通,图中所有顶点度数均为偶数
此题:
(1)并查集判断图是否连通
(2)图中奇数度数的顶点的个数只能为0或者2个
(3)满足(1)(2)要求即输出Zhen,反之亦然
注意:
自环会让度加2
#include<iostream>
#include<string.h>
using namespace std;
const int maxn=35;
int indegree[maxn];
int outdegree[maxn];
int pre[maxn];
void init(int n){
for(int i=1;i<=n;i++){
pre[i]=i;
}
}
int find(int x){
return x==pre[x] ? x : pre[x]=find(pre[x]);
}
int main(){
int t;
cin>>t;
int n,m;
while(t--){
cin>>n>>m;
init(n);
memset(indegree,0,sizeof(indegree));
memset(outdegree,0,sizeof(outdegree));
int u,v;
while(m--){
cin>>u>>v;
indegree[v]++;
outdegree[u]++;
int up=find(u);
int vp=find(v);
if(up!=vp){
pre[up]=vp;
}
}
int cnt=0;
int flag=0;
for(int i=1;i<=n;i++){
if(pre[i]==i){
cnt++;
}
if((indegree[i]+outdegree[i])%2!=0){
flag++;
}
}
if(cnt==1&&(flag==2||flag==0)){
cout<<"Zhen"<<endl;
}
else{
cout<<"Xun"<<endl;
}
}
return 0;
}