强迫症 解题报告
2015-07-05 15:38
225 查看
本题的大意是判断一棵树是否是一棵轴对称树。
然后多组数据,= =少考虑了一种情况导致只有30。
hack点是重心不一定在对称轴上,如果有两个重心的话,就不是了。。(我明明想到了这种情况,但是想错了。。以为这种情况与横过来是等价的。)
具体做法就是找出重心来后随便hash(最好是用异或乱搞一下)。
当然标算其实不是hash,而是直接用的字符串,因为我们需要的是对字符串的长度排序,而字符串的长度和等于O(n),所以总复杂度依然是O(nlogn)的。
= =但是不知道为什么这道题的n这么小。。让我觉得非常诧异。明明可以开到10^5的啊。
然后多组数据,= =少考虑了一种情况导致只有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"); } }
相关文章推荐
- jsp include进去的txt文件出现乱码
- 如何把Applet程序的字节码文件嵌入到HTML文件中???
- php实现短信发送代码
- Unicode-UTF-8
- c#事件与委托
- 集合类的4种遍历方式Block遍历,快速遍历,枚举器,普通遍历
- pr_debug、dev_dbg等动态调试二
- c#事件与委托
- Android分享软件功能的实现
- Activity生命周期
- C-结构体应用(10)
- LeetCode Dungeon Game
- Karatsuba 乘法
- Windows 10 9个恼人问题急需解决
- c++11特性
- Android IOS WebRTC 音视频开发总结(三三)-- Periscope介绍
- e学编程之《设计模式》篇-状态模式
- C++中引用(&)的用法和应用实例
- 【Ogre编程入门与进阶】第十五章 Ogre的“二维”与合成特效
- delphi使用winlicense授权