HDU4812 D Tree(树的点分治)
2016-03-27 17:05
309 查看
题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k。
树的点分治搞了。因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所以这个用乘法逆元搞一下就OK了。还有要注意“治”的各个实现,把时间复杂度“控制”在O(nlogn)。
WA了几次,WA在漏了点到子树根的路径,还有每次分治忘了清空数组。
树的点分治搞了。因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所以这个用乘法逆元搞一下就OK了。还有要注意“治”的各个实现,把时间复杂度“控制”在O(nlogn)。
WA了几次,WA在漏了点到子树根的路径,还有每次分治忘了清空数组。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define INF (1<<30) #define MAXN 111111 struct Edge{ int v,next; }edge[MAXN<<1]; int NE,head[MAXN]; void addEdge(int u,int v){ edge[NE].v=v; edge[NE].next=head[u]; head[u]=NE++; } bool vis[MAXN]; int mini,cen,size[MAXN]; void getSize(int u,int fa){ size[u]=1; for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(v==fa || vis[v]) continue; getSize(v,u); size[u]+=size[v]; } } void getCen(int u,int fa,int &tot){ int res=tot-size[u]; for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(v==fa || vis[v]) continue; getCen(v,u,tot); res=max(res,size[v]); } if(res<mini) mini=res,cen=u; } int getCen(int u){ getSize(u,u); mini=INF; getCen(u,u,size[u]); return cen; } long long ine(long long a){ long long res=1,n=1000001; while(n){ if(n&1) res*=a,res%=1000003; a*=a; a%=1000003; n>>=1; } return res; } int n,k,val[MAXN]; int ansx,ansy; int record[1000003],tn,tmpx[MAXN],tmpy[MAXN],all[MAXN],an; void dfs(int u,int fa,long long dist,int &top){ int v=record[ine(dist)*k%1000003*top%1000003]; if(v){ if(u<v){ if(u<ansx) ansx=u,ansy=v; else if(u==ansx && v<ansy) ansy=u,ansy=v; }else{ if(v<ansx) ansx=v,ansy=u; else if(v==ansx && u<ansy) ansy=v,ansy=u; } } tmpx[tn]=u; tmpy[tn]=dist; ++tn; all[an++]=dist; for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(v==fa || vis[v]) continue; dfs(v,u,dist*val[v]%1000003,top); } } void conquer(int u){ an=0; all[an++]=val[u]; record[val[u]]=u; for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; tn=0; dfs(v,v,(long long)val[u]*val[v]%1000003,val[u]); for(int j=0; j<tn; ++j){ if(record[tmpy[j]]==0 || record[tmpy[j]]>tmpx[j]) record[tmpy[j]]=tmpx[j]; } } for(int i=0; i<an; ++i) record[all[i]]=0; } void divide(int u){ u=getCen(u); vis[u]=1; conquer(u); for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; divide(v); } } int main(){ int a,b; while(~scanf("%d%d",&n,&k)){ for(int i=1; i<=n; ++i){ scanf("%d",val+i); } NE=0; memset(head,-1,sizeof(head)); for(int i=1; i<n; ++i){ scanf("%d%d",&a,&b); addEdge(a,b); addEdge(b,a); } memset(vis,0,sizeof(vis)); ansx=ansy=INF; divide(1); if(ansx==INF) puts("No solution"); else printf("%d %d\n",ansx,ansy); } return 0; }
相关文章推荐
- 【AOS应用基础平台】完好了AOS标签库,和标准标签库完美兼容了
- What is the difference between Simple, Advanced and Parameter data sets?
- 第五周项目二 游戏中的角色类(1)
- 懒虫小鑫
- hihocoder-1284 机会渺茫(水题)
- 敏捷开发方法综述
- Leetcode-Move Zeroes
- disruptor --神奇的缓存行填充2
- poj 2387 Til the Cows Come Home
- BZOJ 1202: [HNOI2005]狡猾的商人
- 悼念512汶川大地震遇难同胞
- Swift入坑--block的定义
- 20145314郑凯杰 《Java程序设计》第4周学习总结
- poj1185
- LeetCode OJ 之 GenerateParenthesis解题报告
- 计算波兰表达式
- 1010.一元多项式求导 (25)
- 迷瘴
- React 教程及其API接口文档
- Ubuntu 12.04 升级到14.04之后,pidgin-sipe 出现的问题: Trouble with the pidgin and self-signed SSL certificate