分析:三分图染色,题意中说到相同集合中的点之间没有边,但是和其它点都有边。
1.如果u1和u2在同一个集合中,那么所有和它没有相连的点都是同一个集合。
2.选择一个数u,那么所有和它没有相连的点都是同一个集合
3.持续第二步多次,如果不能构成3个集合,或者有一个点不在集合中,就不能构成3个集合,输出-1
4.边数要等于(|v1|*|v2| + |v2| * |v3| + |v1| * |v3|)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
int main()
{
int n, m;//n个点,m条边
scanf("%d%d", &n, &m);
vector<set<int>> edges(n + 1);
int a, b;
for (int i = 1; i <= m; ++i)
{
scanf("%d%d", &a, &b);
edges[a].insert(b);
edges[b].insert(a);
}
vector<int> group(n + 1, -1);
for (int g = 1; g <= 3; ++g)
{
int first;//随便找到一个点
for (first = 1; first <= n; ++first) if (group[first] == -1) break;
if (first == n + 1)//找不到
{
puts("-1");
return 0;
}
group[first] = g;
for (int second = 1; second <= n; ++second)
if (second != first && group[second] == -1 && edges[first].find(second) == edges[first].end())
group[second] = g;
}
vector<vector<int>> groups(4);
for (int i = 1; i <= n; ++i)
{
if (group[i] == -1)
{
puts("-1");
return 0;
}
else
groups[group[i]].push_back(i);
}
//数边
int e = 0;
for(int g1 = 1; g1 <= 3; ++g1)
for (int g2 = g1 + 1; g2 <= 3; ++g2)
{
for(int v1 : groups[g1])
for (int v2 : groups[g2])
{
if (edges[v1].find(v2) == edges[v1].end())//不是完全图
{
puts("-1");
return 0;
}
else
{
++e;
}
}
}
if (e != m)
{
puts("-1");
return 0;
}
for (int i = 1; i <= n; ++i)
printf("%d ", group[i]);
return 0;
}