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

发现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
#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 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


你可能感兴趣的:(OI,BZOJ,模拟,瞎搞)