个人感觉这道题出的挺好
给你n个点,m条边,确定出一个三分图,即把点分成三组,每组内的点之间不能直接到达,任意一点必须能直接到达非本组的所有点
首先将1号点定为1组,然后遍历1号点的所有出边,凡是与1号点相连的都为2组,剩余的为1组,在从2组中随便选一个点,遍历这个点的所有出边,凡是与这个点相连的且不为1组的都设为3组
这样先分成三组,然后判断组内的点满不满足题意,即组内的点不可相连
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
int to,next;
}q[600005];
int head[300005],cnt=1;
int d[300005];
vector<int>v1,v2;
void add(int x,int y)
{
q[cnt].to=y;
q[cnt].next=head[x];
head[x]=cnt++;
}
int main()
{
memset(head,-1,sizeof(head));
int n,m,a,b;
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d %d",&a,&b);
v1.push_back(a);v2.push_back(b);
add(a,b);add(b,a);
}
d[1]=1;
int val;
for(int i=head[1];i!=-1;i=q[i].next)
{
int v=q[i].to;
d[v]=2;
val=v;
}
d[val]=2;
for(int i=head[val];i!=-1;i=q[i].next)
{
int v=q[i].to;
if(d[v]==2)
{
d[v]=3;}
}
ll a1=0,a2=0,a3=0;
for(int i=1;i<=n;i++)
{
if(d[i]==0||d[i]==1)
{
d[i]=1;a1++;}
if(d[i]==2)
{
a2++;}
if(d[i]==3)
{
a3++;}
}
if(a1==0||a2==0||a3==0)
{
printf("-1\n");return 0;}
if(a1*a2+a1*a3+a2*a3==m)
{
int flag=1;
for(int i=0;i<m;i++)
{
if(d[v1[i]]==d[v2[i]])
{
flag=0;break;}
}
if(!flag)
{
printf("-1\n");}
else
{
for(int i=1;i<=n;i++)
{
printf("%d ",d[i]);}
printf("\n");
}
}
else
{
printf("-1\n");}
return 0;
}