题意:给定一张不保证联通的简单图,问是否存在染色方案,使得每一个连通块为三分图。
分析:不考虑其他约束,只考虑三分图每一个子集内部没有边相连的约束,先染出一张图。做法为首先对于一个连通块,先选定一个起点u,将u染成1,然后将与u直接相连的点,全部染成2,然后选择一个染成2的点为v,然后将所有与v直接相连的点w染色,其中如果w未染色,那么将w染成1,如果w被染成2,将w染成3。然后再判断这个染色的图是否符合条件。
对于所有的联通块,维护连通块内三种色块中点的数量,如果有一个联通块的某一种色块数量为0,说明连通块内凑不满三个子集,不合法。
对于一个点,如果他直接连接的点数为当前联通块其他两种颜色点的数量之和,则合法,否则不合法。
对于一条边,如果联通颜色相同的点,不合法。
代码中的判断可能有冗余。
代码:
#include <bits/stdc++.h> #define mp make_pair #define debug(x) cout << #x << ": " << x << endl #define pb push_back typedef long long LL; const int maxn = 3e5 + 10; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; using namespace std; int n, m, u, v, col[maxn], f[maxn], sz[maxn]; int find(int x) { return f[x] == -1 ? x : f[x] = find(f[x]); } vector<int> g[maxn]; vector<int> s[maxn][3]; int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> n >> m; for (int i = 0; i < m; ++i) { cin >> u >> v; g[u].pb(v); g[v].pb(u); } for (int i = 1; i <= n; ++i) f[i] = -1; for (int i = 1; i <= n; ++i) { if (col[i] == 0) { col[i] = 1; int fu = find(i); if (g[i].empty()) { cout << -1; exit(0); } int to = g[i][0]; for (int j = 0; j < g[i].size(); ++j) { int _to = g[i][j]; int fv = find(_to); if (fv != fu) f[fv] = fu; col[_to] = 2; } for (int j = 0; j < g[to].size(); ++j) { int _to = g[to][j]; if (_to == i) continue; int fv = find(_to); if (fv != fu) f[fv] = fu; if (col[_to] == 0) col[_to] = 1; else if (col[_to] == 2) col[_to] = 3; else { cout << -1; exit(0); } } } } for (int i = 1; i <= n; ++i) { v = find(i); s[v][col[i] - 1].pb(i); } for (int i = 1; i <= n; ++i) if (!s[i][0].empty() || !s[i][1].empty() || !s[i][2].empty()) { if (s[i][0].empty() || s[i][1].empty() || s[i][2].empty()) { cout << -1; exit(0); } } for (int i = 1; i <= n; ++i) { v = find(i); if (col[i] == 1) { if (s[v][1].size() + s[v][2].size() != g[i].size()) { cout << -1; exit(0); } } else if (col[i] == 2) { if (s[v][0].size() + s[v][2].size() != g[i].size()) { cout << -1; exit(0); } } else if (col[i] == 3) { if (s[v][0].size() + s[v][1].size() != g[i].size()) { cout << -1; exit(0); } } for (int j = 0; j < g[i].size(); ++j) { int to = g[i][j]; if (col[to] == col[i]) { cout << -1; exit(0); } } } for (int i = 1; i <= n; ++i) cout << col[i] << " "; }
codeforces 1228D Complete Tripartite(图论+思维)
原文:https://www.cnblogs.com/smallhester/p/11610616.html