Codeforces 1182D Complete Mirror [树哈希]
中考考完之后第一个AC,纪念一下qwq
思路
简单理解一下题之后就可以发现其实就是要求一个点,使得把它提为根之后整棵树显得非常对称。
很容易想到树哈希来判结构是否相同,而且由于只有完全对称的时候才有用,所以比普通哈希还简单一些……
吗?
你需要求出子树哈希值、祖先哈希值,还要记下来这个点下面是否都相等,还是会有一个捣乱的,还是整个都是乱的。
然后还要特判一个儿子、两个儿子、没有儿子……
于是开开心心地150行了,删掉缺省源之后大概100行。
emmm说的好像不是很清晰,那再说一遍吧。
提为根之后一定是先一段度数为1的点,然后开始分叉,其中每一层的分叉数相同。
如果一个点的儿子的子树全都一样且合法,那就非常好。(非常好是什么鬼啊)
如果有一个特立独行的儿子,那么根肯定在那里面,要把这个儿子给记下来。
如果有两个以上的不一样的或是不合法的,那么就算是废了。
注意还要换根DP一下搞出一个点上方的哈希值,因为提为根之后上面的就变成了一棵子树了。
注意还要各种特判……
代码
哈希值-1表示不合法,\(dn,up\)表示整棵子树/上方,\(W\)表示比较普通的儿子的哈希值,\(son1\)表示记录那个特立独行的儿子。
感谢@litble神仙指出错误,已经改正
#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pli pair<ll,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 101010
#define mod 998244353ll
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__zz=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register int x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__zz]=x%10+48,x/=10);
while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
}
void file()
{
#ifdef NTFOrz
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n;
struct hh{int t,nxt;}edge[sz<<1];
int head[sz],ecnt;
void make_edge(int f,int t)
{
edge[++ecnt]=(hh){t,head[f]};
head[f]=ecnt;
edge[++ecnt]=(hh){f,head[t]};
head[t]=ecnt;
}
ll dn[sz],up[sz];
int son1[sz];
ll W[sz];
int son[sz];
#define v edge[i].t
void dfs1(int x,int fa)
{
int cnt=0;
vector<pli>V;int cc=0,s=0;
go(x) if (v!=fa)
{
dfs1(v,x);++cnt;
if (dn[v]!=-1) V.push_back(MP(dn[v],v));
else ++cc,s=v;
}
if (cnt==0) return (void)(dn[x]=0,W[x]=son1[x]=-1);
sort(V.begin(),V.end());
son[x]=cnt;
if (cc) dn[x]=-1,son1[x]=s;
if (cc>1) return (void)(son1[x]=W[x]=-1);
if (cnt==1)
{
if (cc) W[x]=-1;
else dn[x]=(V[0].fir*sz%mod+1)%mod,W[x]=V[0].fir,son1[x]=-1;
return;
}
if (cc)
{
if (V[0].fir==V[cnt-2].fir) W[x]=V[0].fir;
else W[x]=-1;
return;
}
if (V[0].fir==V[cnt-1].fir) dn[x]=((W[x]=V[0].fir)*sz%mod+cnt)%mod,son1[x]=-1;
else if (V[0].fir==V[cnt-2].fir) dn[x]=-1,W[x]=V[0].fir,son1[x]=V[cnt-1].sec;
else if (V[1].fir==V[cnt-1].fir) dn[x]=-1,W[x]=V[1].fir,son1[x]=V[0].sec;
else dn[x]=W[x]=son1[x]=-1;
}
void dfs2(int x,int fa)
{
go(x) if (v!=fa)
{
if (son[x]==1)
{
if (x==1) up[v]=0;
else if (up[x]==-1) up[v]=-1;
else up[v]=(up[x]*sz%mod+1)%mod;
}
else if (dn[x]!=-1||son1[x]==v)
{
if (x==1) up[v]=(W[x]*sz%mod+son[x]-1)%mod;
else if (up[x]==W[x]&&up[x]!=-1) up[v]=(W[x]*sz%mod+son[x])%mod;
else up[v]=-1;
}
else if (son[x]==2&&son1[x]!=-1)
{
ll w=dn[son1[x]];
if (w==-1) up[v]=-1;
else if (x==1) up[v]=(w*sz%mod+1)%mod;
else if (w==up[x]) up[v]=(w*sz%mod+2)%mod;
else up[v]=-1;
}
else up[v]=-1;
dfs2(v,x);
}
}
int main()
{
file();
read(n);
if (n<=3) return puts("1"),0;
int x,y;
rep(i,1,n-1) read(x,y),make_edge(x,y);
dfs1(1,0);
rep(i,1,n) up[i]=-1;
dfs2(1,0);
if (dn[1]!=-1) return puts("1"),0;
rep(i,2,n) if (up[i]==W[i]&&dn[i]!=-1&&son[i]) return printf("%d",i),0;
rep(i,2,n) if (!son[i]&&up[i]!=-1) return printf("%d",i),0;
puts("-1");
return 0;
}
Codeforces 1182D Complete Mirror [树哈希]的更多相关文章
- Codeforces 1182D Complete Mirror 树的重心乱搞 / 树的直径 / 拓扑排序
题意:给你一颗树,问这颗树是否存在一个根,使得对于任意两点,如果它们到根的距离相同,那么它们的度必须相等. 思路1:树的重心乱搞 根据样例发现,树的重心可能是答案,所以我们可以先判断一下树的重心可不可 ...
- [codeforces 241]C. Mirror Box
[codeforces 241]C. Mirror Box 试题描述 Mirror Box is a name of a popular game in the Iranian National Am ...
- Colored Sticks (字典树哈希+并查集+欧拉路)
Time Limit: 5000MS Memory Limit: 128000K Total Submissions: 27704 Accepted: 7336 Description You ...
- UOJ#373. 【ZJOI2018】线图 搜索,树哈希,动态规划
原文链接www.cnblogs.com/zhouzhendong/p/UOJ373.html 前言 真是一道毒瘤题.UOJ卡常毒瘤++.我卡了1.5h的常数才过QAQ Orzjry 标算居然是指数做法 ...
- LOJ.6066.[2017山东一轮集训Day3]第二题(树哈希 二分)
LOJ 被一件不愉快的小事浪费了一个小时= =. 表示自己(OI方面的)智商没救了=-= 比较显然 二分+树哈希.考虑对树的括号序列进行哈希. 那么每个点的\(k\)子树的括号序列,就是一段区间去掉距 ...
- 【BZOJ5211】[ZJOI2018]线图(树哈希,动态规划)
[BZOJ5211][ZJOI2018]线图(树哈希,动态规划) 题面 BZOJ 洛谷 题解 吉老师的题目是真的神仙啊. 去年去现场这题似乎骗了\(20\)分就滚粗了? 首先\(k=2\)直接算\(k ...
- BZOJ.4337.[BJOI2015]树的同构(树哈希)
BZOJ 洛谷 \(Description\) 给定\(n\)棵无根树.对每棵树,输出与它同构的树的最小编号. \(n及每棵树的点数\leq 50\). \(Solution\) 对于一棵无根树,它的 ...
- bzoj4337: BJOI2015 树的同构 树哈希判同构
题目链接 bzoj4337: BJOI2015 树的同构 题解 树哈希的一种方法 对于每各节点的哈希值为hash[x] = hash[sonk[x]] * p[k]; p为素数表 代码 #includ ...
- 【BZOJ3162】独钓寒江雪(树哈希,动态规划)
[BZOJ3162]独钓寒江雪(树哈希,动态规划) 题面 BZOJ 题解 忽然翻到这道题目,突然发现就是前几天一道考试题目... 题解: 树哈希,既然只考虑这一棵树,那么,如果两个点为根是同构的, 他 ...
随机推荐
- 启动 kibana 失败
错误信息: Sending Logstash logs to /usr/local/logstash-6.4.3/logs which is now configured via log4j2.pro ...
- App功能测试点总结
1.手机操作系统android(谷歌).ios(苹果).Windows phone(微软).Symbian(诺基亚).BlackBerry OS(黑莓).windows mobile(微软),目前主流 ...
- ExcelReport.cs Excel操作类、实例源码下载
标题一.告别ASP.NET操作EXCEL的烦恼标题二.ASP.NET操作EXCEL 合并单元格 大全... cnblogs/hanzhaoxin/韩兆新的博客园ExcelReport第一篇:使用Exc ...
- 线程二(Monitor)
Monitor 类的命名空间是 System.Threading,它的用法和 lock 本质是一样的. 使用 Monitor 类锁定资源的代码如下. Monitor.Enter(object); tr ...
- VBA日期时间函数(十三)
VBScript日期和时间函数帮助开发人员将日期和时间从一种格式转换为另一种格式,或以适合特定条件的格式表示日期或时间值. 日期函数 编号 函数 描述 1 Date 一个函数,它返回当前的系统日期. ...
- iOS - Scenekit3D引擎初探之 - 导出DAE文件(3Dmax为例)
DAE文件格式是3D交互文件格式,一般用于多个图形程序之间交换数字数据,Autodesk专有并在COLLADA(COLLAborative Design Activity)基础上改进创建的XML框架的 ...
- 图片预先加载 preloadjs
<body><div class="loading"> <div class="progress"></div> ...
- ELK文档--ELK简介
请参考:http://www.cnblogs.com/aresxin/p/8035137.html
- CSS之属相相关
一.padding与margin padding:就是内边距的意思,它是边框到内容之间的距离 另外padding的区域是有背景颜色的.并且背景颜色和内容的颜色一样.也就是说background-col ...
- c++混合使用不同标准编译潜在的问题
最近项目使用的C++的版本到C++11了,但是由于有些静态库(.a)没有源码,因此链接时还在使用非C++11版本的库文件.目前跑了几天,似乎是没出什么问题,但是我还是想说一下这样做有哪些潜在的风险. ...