题目大意:每张多米诺骨牌上有1到n之间的两个数字,现给出n张牌,问能不能把骨牌分成两副,使得每一副骨牌中没有重复的数字。
思路:题意比较类似于二分图,然后我们发现如果我们将一张骨牌上的两个数之间建边,那么会构成很多环,只有每个环的大小都是偶数,才能将骨牌平分
#include<__msvc_all_public_headers.hpp>
//#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
vector<int>g[N];
int n;
bool vis[N];
int dfs(int u)//记录当前的点的编号
{
vis[u] = 1;
for (int i = 0; i < g[u].size(); i++)
{//遍历当前点连接的所有边
int v = g[u][i];
if (vis[v])
continue;
return dfs(v) + 1;//记录遍历过的点数
}
return 1;
}
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
{
bool flag = 1;
cin >> n;
for (int i = 1; i <= n; i++)
{
g[i].clear();
vis[i] = 0;
}
for (int i = 1; i <= n; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);//邻接表存图
if (u == v || g[u].size() > 2 || g[v].size() > 2)
flag = 0;//输入的数字数量不满足条件
}
for (int i = 1; i <= n; i++)
{//遍历所有连通分量
if (!vis[i]&&flag )
{
if (dfs(i) & 1)
{//这个连通分量的大小是奇数
flag = 0;
break;
}
}
}
if (flag)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}