BZOJ 4466 [Jsoi2013]超立方体【模拟

版权声明:Flaze的代码自带大常数,应该没人转……如果有转载的话还是带个名字好了 https://blog.csdn.net/Flaze_/article/details/53422695

发现n维超立方体有2^n个定点,2^(n-1)*n条棱,每个点的度数为n

发现只有在二进制表示下 只有一位不同的两个点之间才有边


于是check上面那三个点可以先判断-1


用id[i] 表示 i 号点的标号

然后进行标号把原来的0号点标为0,与它相邻的点分别标为2,4,8,16....

从与0号点相邻的点开始bfs,每个点记录dis[i],表示i号点与0号点的距离+1(为了方便 dis[0] = 1)

对于与 i 相邻的点 j ,如果dis[j] == dis[i] + 1 ,id[j] |= id[i]


最后check每个边两边的点是否合法,是否有重复的标号


#include<bits/stdc++.h>
#define MAXN 32800
#define MAXM 1000005
using namespace std;	int Q,n,m;
int Base,tmp_base;
inline int read(){
	register char ch = getchar();
	while(!isdigit(ch))	ch = getchar();
	register int rtn = 0;
	while(isdigit(ch))	rtn = rtn*10 + ch - '0' , ch = getchar();
	return rtn;
}
//=======================================
struct t1{
	int to,nxt;
}edge[MAXM<<1];	int cnt_edge;
int dex[MAXN];
int fst[MAXN];
inline void addedge(int x,int y){
	++dex[x] , ++dex[y];
	edge[++cnt_edge].to = y;
	edge[cnt_edge].nxt = fst[x];
	fst[x] = cnt_edge;

	edge[++cnt_edge].to = x;
	edge[cnt_edge].nxt = fst[y];
	fst[y] = cnt_edge;
}

int id[MAXN];
int dis[MAXN];

queue<int> q;

inline void bfs(){
	while(!q.empty()){
		int now = q.front();
		q.pop();
		
		for(int tmp = fst[now];tmp;tmp=edge[tmp].nxt){
			int aim = edge[tmp].to;
			if(!dis[aim]){
				dis[aim] = dis[now] + 1;
				q.push(aim);
				id[aim] = id[now];
			}else{
				if(dis[aim] == dis[now] + 1)
					id[aim] |= id[now];
			}
		}
	}
}

int vis[MAXN];
inline void check(){
//	__builtin_popcount()
	memset(vis,0,sizeof vis);
	for(int i=0;i<n;++i){
		if(vis[id[i]])	return void(puts("-1"));
		vis[id[i]] = 1;
		for(int tmp = fst[i];tmp;tmp=edge[tmp].nxt){
			if(__builtin_popcount(id[i]^id[edge[tmp].to]) ^ 1)
				return void(puts("-1"));
		}
	}
	for(int i=0;i<n;++i)	printf("%d ",id[i]);
	puts("");
}

int main(){
//	freopen("1.in","r",stdin);
	Q = read();
	while(Q--){
		memset(fst,0,sizeof fst);
		memset(edge,0,sizeof edge);
		memset(id,0,sizeof id);
		memset(dex,0,sizeof dex);
		memset(dis,0,sizeof dis);

		cnt_edge = 0;
		n = read() , m = read();
		for(Base = 0 , tmp_base = 1;tmp_base<n;++Base , tmp_base<<=1);
		for(int i=1;i<=m;++i)	addedge(read(),read());

		if((tmp_base^n)||(m^((n/2)*Base))){
			puts("-1");
			continue;
		}

		int flag = 0;
		for(int i=0;i<n;++i)	if(dex[i]^(Base)){
			puts("-1");
			flag = 1;
			break;
		}
		if(flag)	continue;

		id[0] = 0;
		dis[0] = 1;
		for(int tmp = fst[0],i = 1;tmp;tmp = edge[tmp].nxt , i<<=1)
			id[edge[tmp].to] = i , q.push(edge[tmp].to) , dis[edge[tmp].to] = 2;

		bfs();
		check();
	}
	return 0;
} 


没有更多推荐了,返回首页