这题有毒
首先,我们发现如果一张图合法,那么点数为
2n
,边为
2n−1∗n
每个点度数为
n
,并且图中没有奇数长度的环
我们可以假设
然后bfs一遍,确定每个点编号
怎么bfs呢?我们注意到,两个点有边当且仅当两个点新编号二进制位差
1
假设
最后判一下每条边是否合法,编号是不是
#include<bits/stdc++.h>
#define ms(a) memset(a,0,sizeof a)
using namespace std;
inline void splay(int &v){
v=0;char c=0;int p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
#define N 32769
#define M 2000010
int nxt[M],fir[N],sz,to[M],vis[N],n,m,dl[N],val[N],dis[N],p[N],du[N];
void add(int x,int y){
nxt[++sz]=fir[x];fir[x]=sz;to[sz]=y;du[x]++;
}
bool is(int x){
if(x==0)return 0;
return x==(x&-x);
}
int main(){
int q;for(splay(q);q;q--){
splay(n),splay(m);
sz=0;bool fl=1;
ms(fir),ms(du),ms(vis),ms(dis),ms(val);
for(int i=1;i<=m;i++){
int x,y;splay(x),splay(y);
add(x,y),add(y,x);
}
if(n==1){puts(m?"-1":"0");continue;}
int bit=0;
for(int i=0;i<=20;i++){
if((1<<i)==n)bit=i;
}
if(!bit){puts("-1");continue;}
if((1<<(bit-1))*bit!=m){puts("-1");continue;}
for(int i=0;i<n;i++)if(du[i]!=bit)fl=0;
if(!fl){puts("-1");continue;}
int head=0,tail=0,tot=-1;vis[0]=1;
for(int u=fir[0];u;u=nxt[u]){
dl[++tail]=to[u];dis[to[u]]=1;
val[to[u]]=1<<(++tot);
vis[to[u]]=1;
}
while(head!=tail){
int v=dl[++head];
for(int u=fir[v];u;u=nxt[u]){
if(!vis[to[u]]){
vis[to[u]]=1;dis[to[u]]=dis[v]+1;
dl[++tail]=to[u];
}
if(dis[to[u]]==dis[v]+1)val[to[u]]|=val[v];
}
}
for(int i=0;i<n;i++){
for(int u=fir[i];u;u=nxt[u]){
if(!is(val[i]^val[to[u]])){
fl=0;
}
}
}
for(int i=0;i<n;i++)p[i]=val[i];
sort(p,p+n);
for(int i=0;i<n;i++)if(p[i]!=i)fl=0;
if(!fl){puts("-1");continue;}
else{
for(int i=0;i<n;i++){
printf("%d ",val[i]);
}
printf("\n");
}
}
}