分析:三分图染色,题意中说到相同集合中的点之间没有边,但是和其它点都有边。
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;
}