您的位置:首页 > 其它

强迫症 解题报告

2015-07-05 15:38 225 查看
本题的大意是判断一棵树是否是一棵轴对称树。

然后多组数据,= =少考虑了一种情况导致只有30。

hack点是重心不一定在对称轴上,如果有两个重心的话,就不是了。。(我明明想到了这种情况,但是想错了。。以为这种情况与横过来是等价的。)

具体做法就是找出重心来后随便hash(最好是用异或乱搞一下)。

当然标算其实不是hash,而是直接用的字符串,因为我们需要的是对字符串的长度排序,而字符串的长度和等于O(n),所以总复杂度依然是O(nlogn)的。

= =但是不知道为什么这道题的n这么小。。让我觉得非常诧异。明明可以开到10^5的啊。

[code]#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
#include<process.h>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#define Base 233
inline void in(int &x){
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    x=0;
    for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
}
inline unsigned Rand(){
    return rand()<<16|rand();
}
int color[10005];
unsigned chash[10005],phash[10005];
int next[20005],ptr[10005],succ[20005],etot;
inline void addedge(int u,int v){
    next[etot]=ptr[u],ptr[u]=etot,succ[etot++]=v;
}
int size[10005],Size,fa[10005];
void sizedfs(int node){
    size[node]=1;
    for(int i=ptr[node];i;i=next[i])
        if(succ[i]!=fa[node]){
            fa[succ[i]]=node;
            sizedfs(succ[i]);
            size[node]+=size[succ[i]];
        }
}
void hdfs(int node,int ftr){
    phash[node]=0;
    for(int i=ptr[node];i;i=next[i])
        if(succ[i]!=ftr){
            hdfs(succ[i],node);
            phash[node]+=phash[succ[i]]*3;
        }
    phash[node]=(phash[node]*Base)^chash[color[node]];
}
bool check(int node,int ftr){
    int ans=0;
    for(int i=ptr[node];i;i=next[i])
        if(succ[i]!=ftr)
            ans^=phash[succ[i]];
    if(!ans)return 1;
    for(int i=ptr[node];i;i=next[i])
        if(succ[i]!=ftr&&ans==phash[succ[i]])
            return check(succ[i],node);
    return 0;
}
struct SS{
    unsigned sonhash;
    bool flag;
    bool operator < (const SS & o)const{
        return sonhash<o.sonhash;
    }
    bool operator == (const SS &o)const{
        return sonhash==o.sonhash;
    }
}son[10005];
inline bool bin(int node){
    int i,j;
    //找重心。
    fa[node]=0;
    sizedfs(node);
    Size=size[node];
    do{
        for(i=ptr[node];i;i=next[i])
            if(succ[i]!=fa[node])
                if(size[succ[i]]>Size>>1){
                    node=succ[i];
                    break;
                }
                else
                    if((~Size&1)&&size[succ[i]]==Size>>1){
                        hdfs(node,succ[i]),hdfs(succ[i],node);
                        if(phash[node]==phash[succ[i]])return 1;
                    }
    }while(i);
    //cout<<"-------"<<node<<"-------\n";
    //搞出每棵子树的hash
    hdfs(node,0);
    //处理出每个子树是否可行
    int sontot=0;
    for(i=ptr[node];i;i=next[i])son[sontot++]=(SS){phash[succ[i]],check(succ[i],node)};
    //for(j=0,i=ptr[node];i;i=next[i],++j)cout<<succ[i]<<":"<<phash[succ[i]]<<","<<son[j].flag<<endl;
    sort(son,son+sontot);
    son[sontot]=(SS){-1};
    //判断是否存在合法链,要求个数<3即可。
    int tot=0;
    for(i=0;i<sontot;i=j){
        j=i+1;
        while(son[i]==son[j])++j;
        if(j-i&1)
            if(son[i].flag)++tot;
            else break;
    }
    if(i==sontot&&tot<3)return 1;
    else return 0;
}
int main(){
    freopen("tree.in","r",stdin);
    //freopen("tree.out","w",stdout);
    int T,n,i,j;
    for(i=26;i--;)chash[i]=Rand();
    in(T);
    int u,v;
    while(T--){
        in(n);
        for(i=1;i<=n;++i){
            color[i]=getchar();
            while(color[i]<'A'||color[i]>'Z')color[i]=getchar();
            color[i]-='A';
        }
        memset(ptr,0,sizeof(ptr));
        etot=2;
        for(i=n;--i;){
            in(u),in(v);
            addedge(u,v),addedge(v,u);
        }
        if(bin(1))puts("SYMMETRIC");
        else puts("NOT SYMMETRIC");
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: