bzoj4466 超立方体

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4466 超立方体相关的知识,希望对你有一定的参考价值。

Description

超立方体是立方体在高维空间内的拓展(其在 2 维情况下退化为正方形,1
维情况下退化成线段)。在理论计算机科学领域里,超立方体往往可以和 2 进制
编码联系到一起。对理论计算机科学颇有研究的 Will 自然也会对超立方体有着
自己的思考。 
技术分享
上图就是在 0~4 维空间内超立方体所对应的图形。显然我们可以把超立方
体的每个顶点看成一个点,每一条棱看成一条边,这样就会得到一个无向图,我
们称之为超立方图。 
D维空间内的超立方图有 2D个点,我们把这些点从0到2D-1依次编号。 
有一个有趣而重要的充要结论是:一定存在一种编号的方式,使得图中任意
两个有边相连的顶点的编号的 2进制码中,恰好有一位不同。 
在 2维和3维空间内这个结论可以这样形象的理解: 
对于 2维空间,我们只要把这个正方形放到第一象限内,使得 4个顶点的坐
标按逆时针顺序依次为(0,0),(1,0),(1,1),(0,1),然后再把坐标看成 2位2进制
数,依次将这 4个点编号为 0,1,3,2即可。 
对于 3维空间,同样我们可以将立方体的一个顶点与原点重合,并使得所有
棱均平行于坐标轴,然后分别确定这8个点的坐标,最后把3维空间内的坐标看
成一个3位2进制数即可。对于D维空间,以此类推。 
现在对于一个 N 个点M条边的无向图(每个点从 0到N-1编号),Will 希望
知道这个图是否同构于一个超立方图。

Input

第一行包含一个整数 Q表示此数据中一共包含 Q个询问。
接下来 Q组询问,每一组询问的输入格式如下:
第一行包含两个整数 N 和M,
接下来 M 行,每行 2 个不同的整数 x,y,表示图中存在一条无向边连接编
号为x和y的点(0 < = x,y < N)
Q<=3,N<=32768,M<=1000000

Output

对于每一个询问分别输出一行,内容如下: 
1、如果询问中给定的图不同构于任何一个超立方图,输出-1; 
2、如果同构于某一个超立方图,那么请给图中这N 个点重新编号,并在这
一行输出 N 个用空格隔开的整数,表示原图中每个点新的编号,使得重新编号
后,满足题目中所述的结论。 
注意:输出文件的每一行,要么仅包含一个整数-1,要么则应包含一个由 0
到N-1这 N 个数组成的排列。如果有多组解输出任意一个均可。

一个超立方体图满足:

1.每个顶点有相同度数k

2.共2k个顶点,k2k-1条边

3.标号后任意边两端标号二进制表示只相差1位

4.每个点相邻的所有点的标号与这个点标号不同的二进制位互不相同

不符合1.2.直接输出-1,符合1.2.的可以先bfs一次得到标号并验证标号是否合法(标号不重复且符合3.4.)

bfs时,任取一个点标号0,其相邻点标号为2的幂,取未标号且与已标号点相邻的点,将其标号为相邻已标号点的标号的按位或值

#include<cstdio>
inline int input(){
    int x=0,c=getchar();
    while(c>57||c<48)c=getchar();
    while(c>47&&c<58)x=x*10+c-48,c=getchar();
    return x;
}
const int N=32768;
int id[N],rs[N],ed[N];
int e[16][N],p[N],dc[N+1];
int q[N],ql=0,qr=0;
int n,m,a,b;
void chk(){
    n=input();
    m=input();
    bool un=0;
    ql=qr=0;
    int D=dc[n];
    if(n==1&&m==0){
        puts("0");
        return;
    }
    if(!D||m*2!=n*D)un=1;
    if(!un)
    for(int i=0;i<N;i++)p[i]=ed[i]=id[i]=rs[i]=0;
    while(m--){
        a=input(),b=input();
        if(p[a]>=D||p[b]>=D)un=1;
        if(un)continue;
        e[p[a]++][a]=b;
        e[p[b]++][b]=a;
    }
    ed[0]=1;
    if(!un)
    for(int i=0;i<p[0];i++){
        int w=e[i][0];
        if(ed[w]){un=1;break;}
        ed[w]=1;
        q[qr++]=w;
        id[w]=1<<i;
    }
    if(!un)
    while(ql<qr){
        int w=q[ql++];
        ed[w]=1;
        for(int i=0;i<p[w];i++){
            int u=e[i][w];
            if(ed[u]==1)continue;
            id[u]|=id[w];
            if(!ed[u]){
                ed[u]=2;
                q[qr++]=u;
            }
        }
    }
    if(!un)
    for(int i=0;i<n;i++){
        if(rs[id[i]]){un=1;break;}
        rs[id[i]]=i;
    }
    if(!un)
    for(int i=0;i<n&&!un;i++){
        int s=0;
        for(int j=0;j<p[i];j++){
            int u=e[j][i];
            int c=id[u]^id[i];
            if(s&c){un=1;break;}
            if(c!=(c&-c)){un=1;break;}
            s|=c;
        }
        if(s+1!=n)un=1;
    }
    if(un)puts("-1");
    else{
        printf("%d",id[0]);
        for(int i=1;i<n;i++)printf(" %d",id[i]);
        putchar(10);
    }
}
int main(){
    for(int i=0;i<16;i++)dc[1<<i]=i;
    int T=input();
    while(T--)chk();
    return 0;
}

 

以上是关于bzoj4466 超立方体的主要内容,如果未能解决你的问题,请参考以下文章

Hadoop超立方体

论文复现:模拟风电不确定性——拉丁超立方抽样生成及缩减场景(Matlab全代码)

论文复现:模拟风电不确定性——拉丁超立方抽样生成及缩减场景(Matlab全代码)

风光负荷出力各场景及概率场景削减负荷点的拉丁超立方抽样(Matlab代码实现)

超实用的php代码片段

为啥模板测试不丢弃片段?