【Codeforces Round #589 D】Complete Tripartite

题目链接

Complete Tripartite

Introduce

You have a simple undirected graph consisting of (n) vertices and (m) edges. The graph doesn't contain self-loops, there is at most one edge between a pair of vertices. The given graph can be disconnected.
Let's make a definition.
Let (v_1) and (v_2) be two some nonempty subsets of vertices that do not intersect. Let (f(v_1,v_2)) be true if and only if all the conditions are satisfied:

  1. There are no edges with both endpoints in vertex set (v_1).
  2. There are no edges with both endpoints in vertex set (v_2).
  3. For every two vertices (x) and (y) such that (x) is in (v_1) and (y) is in (v_2), there is an edge between (x) and (y).
    Create three vertex sets ((v_1, v_2, v_3)) which satisfy the conditions below;
  4. All vertex sets should not be empty.
  5. Each vertex should be assigned to only one vertex set.
  6. (f(v_1,v_2)), (f(v_2,v_3)), (f(v_3,v_1)) are all true.
    Is it possible to create such three vertex sets? If it's possible, print matching vertex set for each vertex.

Input

The first line contains two integers (n) and (m) ((3≤n≤10^5, 0≤m≤min(3⋅10^5,frac{n(n−1)}{2}) )) — the number of vertices and edges in the graph.
The (i)-th of the next (m) lines contains two integers (a_i) and (b_i) ((1≤a_i<b_i≤n)) — it means there is an edge between (a_i) and (b_i). The graph doesn't contain self-loops, there is at most one edge between a pair of vertices. The given graph can be disconnected.

Output

If the answer exists, print (n) integers. (i)-th integer means the vertex set number (from (1) to (3)) of (i)-th vertex. Otherwise, print (−1).
If there are multiple answers, print any.

Examples

input

6 11
1 2
1 3
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6

output

1 2 2 3 3 3 

input

4 6
1 2
1 3
1 4
2 3
2 4
3 4

output

-1

Note

In the first example, if (v_1={1}), (v_2={2,3}), and (v_3={4,5,6}) then vertex sets will satisfy all conditions. But you can assign vertices to vertex sets in a different way; Other answers like "2 3 3 1 1 1" will be accepted as well.

In the second example, it's impossible to make such vertex sets.

题解

题意要求把一个没有自环的图上的点分成三个集合,要求每个集合内的点不能有边相连,而且每个点都要有和另外两个集合内的所有点有一条边相连。
我首先就想到了暴力枚举每个点可以在的集合,看看能不能把每个点都分到一个集合里,在枚举的过程中再加一些优化。
在判断一个点能否在当前集合的时候,我枚举了一下这个点的每条边,如果和当前集合的点有连边,就(return 0;)
我用(as[j])来表示(j)这个点当前在的集合的编号。
再用(ss[j])表示编号为(j)的集合里有多少个点,用(ss[j])来判断当前点是否和本身集合外的所有点有连边(枚举边后判断和本身集合外的点的连边数是否等于另外两个集合的点数和)。
只要找到了一组可行的集合分布方案,就可以输出方案,直接结束程序了。
当枚举完所有点都找不到方案时,就输出(-1)
上代码:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int x,y;
struct aa{
	int to,nxt;
}p[600009];
int h[300009],len;
void add(int x,int y){
	if(y>=x) return;//每个点判断在那个集合时已在集合里的点的序号一定都小于这个点,所以指向序号大的点的边对于判断集合没有影响。
	p[++len].to=y;
	p[len].nxt=h[x];
	h[x]=len;
}
int as[300009];
int ss[9];
bool pd(int x,int uu){
	int s=0;
	for(int j=h[x];j;j=p[j].nxt){
		if(p[j].to>=x) continue;
		if(as[p[j].to]==uu) return 0;
		else s++;
	}
	if(s!=x-1-ss[uu]) return 0;
	return 1;
}
int l=1;
void dfs(int u){
	if(u==n+1){
		if(ss[3]==0 || ss[2]==0 || ss[1]==0) return;
		for(int j=1;j<=n;j++)
			printf("%d ",as[j]);
		exit(0);
	}
	for(int j=1;j<=l;j++)//因为当两个集合都为空时两个集合的序号没有区别,所以这里做了点优化(实际上也减少不了多少时间)
		if(pd(u,j)){
			as[u]=j;
			ss[j]++;
			bool mmm=0;
			if(l<=2 && ss[l]>0){
				mmm=1;
				l++;
			}
			dfs(u+1);
			l-=mmm;
			ss[j]--;
		}
}
int main() {
	scanf("%d%d",&n,&m);
	for(int j=1;j<=m;j++){
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	dfs(1);
	printf("-1");
	return 0;
}
原文地址:https://www.cnblogs.com/linjiale/p/11613242.html