您的位置:首页 > Web前端 > JavaScript

bzoj 4466 : [Jsoi2013]超立方体

2016-05-23 16:38 615 查看
这题有毒

首先,我们发现如果一张图合法,那么点数为2n2^{n},边为2n−1∗n2^{n-1}*n

每个点度数为nn,并且图中没有奇数长度的环

我们可以假设00号点的新编号为00,并且把00点相连的边编号赋成1,2,4,8,16……1,2,4,8,16……

然后bfs一遍,确定每个点编号

怎么bfs呢?我们注意到,两个点有边当且仅当两个点新编号二进制位差11

假设a−ba-b有边且a−ca-c有边,且b,cb,c到00号点距为x,aa到00号点距为x+1x+1,那么aa点编号=b=b点编号 oror cc点编号

最后判一下每条边是否合法,编号是不是1到n1到n就行了

#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
,sz,to[M],vis
,n,m,dl
,val
,dis
,p
,du
;
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");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: