题意:
给了个图 让他成为题意的3分图。
3 3 3 个集合形成了一个环的关系,所以随意调换顺序是无所谓的.
然后随便让 1 1 1 个点成为第 2 2 2 集合,那么不与这个点连边的一定也属于第二集合.
然后再随便找一个与所选点有连边的点,将这个设为第 3 3 3 集合中的点,然后与这个点有连边且不为第二集合的就是第一集合的.
构造出了 3 3 3 个集合后再判断一下是否不合法即可.
几个判断方式:
-
一个集合中不能有连边
-
任意一个集合中所有点出边的数量应该相同.
-
任何一个点集都不能为空.
AC代码:
const int N = 2e5 + 10;
vector<int> G[N];
int vised[N], ty[N], cnt[N];
int n, m, flag = 0;
int main()
{
sdd(n, m);
rep(i, 1, m)
{
int u, v;
sdd(u, v);
G[u].push_back(v);
G[v].push_back(u);
}
ty[1] = 2;
cnt[2] = 1;
rep(i, 0, G[1].size() - 1)
{
int v = G[1][i];
vised[v] = 1;
}
rep(i, 2, n)
{
if (!vised[i])
{
ty[i] = 2;
++cnt[2];
}
}
rep(i, 1, n)
{
if (vised[i])
{
rep(j, 0, G[1].size() - 1)
{
int v = G[i][j];
if (!ty[v])
{
ty[v] = 1;
++cnt[1];
}
}
ty[i] = 3;
++cnt[3];
break;
}
}
rep(i, 1, n)
{
if (!ty[i])
{
ty[i] = 3;
++cnt[3];
}
}
rep(i, 1, n)
{
if (ty[i] == 1)
{
rep(j, 0, G[1].size() - 1)
{
int v = G[i][j];
if (ty[v] == 1)
flag = 1;
}
if (G[i].size() != cnt[2] + cnt[3])
flag = 1;
}
if (ty[i] == 2)
{
rep(j, 0, G[1].size() - 1)
{
int v = G[i][j];
if (ty[v] == 2)
flag = 1;
}
if (G[i].size() != cnt[1] + cnt[3])
flag = 1;
}
if (ty[i] == 3)
{
rep(j, 0, G[1].size() - 1)
{
int v = G[i][j];
if (ty[v] == 3)
flag = 1;
}
if (G[i].size() != cnt[1] + cnt[2])
flag = 1;
}
}
rep(i, 1, n)
{
if (!ty[i])
flag = 1;
}
if (!cnt[1] || !cnt[2] || !cnt[3])
flag = 1;
if (flag)
puts("-1");
else
{
rep(i, 1, n)
printf("%d%c", ty[i], i == n ? '\n' : ' ');
}
return 0;
}