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 题解 忽然翻到这道题目,突然发现就是前几天一道考试题目... 题解: 树哈希,既然只考虑这一棵树,那么,如果两个点为根是同构的, 他 ...
随机推荐
- maven配置阿里镜像
在conf\settings.xml 在<mirrors>里面添加 <mirror> <id>nexus-aliyun</id> < ...
- Tomcat一闪而过的调试方法
很少用tomcat来部署,都是用springboot微服务.只是以前学的时候搞demo试过而已. 软件测试的期末作业要求要测一个Javaweb的项目,给了一个包然后要求部署在tomcat中并启动. 然 ...
- .Net Core Mvc/WebApi 返回结果封装
一.背景 为了方便开发,简化代码,也为了与前端方便对接,需要对接口服务返回结果进行统一处理. .Net Core 中返回结果的处理与 .Net Framework 中的处理不一样. .Net Core ...
- 外汇MT4编程手册
1.为了最大的方便用户,交易中断的一些变量可以从智能系统输入. AccountNumber-账号(同义词:AccNum) Ask –卖价(买方出价) Balance – 交易账户的余额值 Bars – ...
- vue -- 数组过滤 filter (vue 表格)
如下图: 左边表格滑动滚轮,可以自动赋值右边表格: 现在是后台只有一个接口,把整个页面的数据全部返回出来了, 左边表格滑动到每一项时显示右边表格内容,但是需要code相同: 问题: 右边表格 ...
- "工作激发了我的热情,并不断激励着我” - SAP成都研究院Jerry Wang
SAP 为员工提供了与 SAP的优秀人才以及全球客户和合作伙伴共事的绝佳机会.我相信,只要你努力工作,充满激情,你就能在这里获得成功. -- Jerry Wang 加入SAP 我是从中国电子科技大学的 ...
- Linux命令——killall 、kill 、pkill、xkill
参考:killall .kill .pkill 命令详解 Using kill, killall, and pkill 4 Ways to Kill a Process – kill, killall ...
- django工作原理简介
django工作原理简介 先简单的介绍一下django的工作原理,其中还会涉及到Middleware(中间件,包括request, view, exception, response),URLConf ...
- Tensorflow&CNN:裂纹分类
版权声明:本文为博主原创文章,转载 请注明出处:https://blog.csdn.net/sc2079/article/details/90478551 - 写在前面 本科毕业设计终于告一段落了.特 ...
- MySQL服务器2
1.sql的基本语法 对数据库 create database db1; 创建数据库 对表: create database t1(id int,name char(10)); 创建表 show cr ...