https://www.luogu.com.cn/problem/CF1702E
轉化題意
把所有數連邊,判斷是否為二分圖。
染色法
void solve() {
#define tests
int n;
std::cin >> n;
std::map<int, std::vector<int>> edge;
std::vector<bool> used(n + 1);
bool ok(true);
for (int i = 0; i < n; i++) {
int a, b;
std::cin >> a >> b;
edge[a].push_back(b);
edge[b].push_back(a);
if (a == b or sz(edge[a]) > 2 or sz(edge[b]) > 2) {ok = false;}//出現次數大於二
}
if (not ok) {NO; return ;}
auto dfs = [&](auto self, int now) -> int {
used[now] = true;
for (auto to : edge[now]) if (not used[to]) {
return self(self, to) + 1;
}
return 1;
};//其實也是判斷有沒有奇環,顯然總數加起來如果是奇數就是奇環
for (int i = 0; i < n; i++) {
if (not used[i + 1] and (dfs(dfs, i + 1) & 1)) {
ok = false;
}
}
ok ? YES : NO;
}
擴充套件域並查集
//擴充套件域並查集維護是否為二分圖
//構造出x的敵人x+n和y的敵人y+n
//因為是分成兩個集合,所以只要構造一個敵人(即另一個與自己相等的數,但不能放到同一個集合內所以稱為敵人)
//把x和y的敵人合併,y和x的敵人合併
//如果x和自己的敵人在一個並查集,就不合法
void solve() {
#define tests
int n;
std::cin >> n;
std::vector<int> cnt(n);
DSU dsu(n * 2);
for (int i = 0; i < n; i++) {
int x, y;
std::cin >> x >> y;
x--, y--;
cnt[x]++; cnt[y]++;
dsu.merge(x, y + n); dsu.merge(x + n, y);
}
bool ok(true);
for (int i = 0; i < n; i++) {
if (cnt[i] > 2) ok = false;
if (dsu.find(i) == dsu.find(i + n)) ok = false;
}
ok ? YES : NO;
}