题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k。

树的点分治搞了。因为是点权过根的两条路径的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<<];
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]=;
for(int i=head[u]; i!=-; 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!=-; 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=,n=;
while(n){
if(n&) res*=a,res%=;
a*=a; a%=;
n>>=;
}
return res;
}
int n,k,val[MAXN];
int ansx,ansy;
int record[],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%*top%];
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!=-; i=edge[i].next){
int v=edge[i].v;
if(v==fa || vis[v]) continue;
dfs(v,u,dist*val[v]%,top);
}
}
void conquer(int u){
an=;
all[an++]=val[u];
record[val[u]]=u;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue;
tn=;
dfs(v,v,(long long)val[u]*val[v]%,val[u]);
for(int j=; j<tn; ++j){
if(record[tmpy[j]]== || record[tmpy[j]]>tmpx[j]) record[tmpy[j]]=tmpx[j];
}
}
for(int i=; i<an; ++i) record[all[i]]=;
}
void divide(int u){
u=getCen(u);
vis[u]=;
conquer(u);
for(int i=head[u]; i!=-; 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=; i<=n; ++i){
scanf("%d",val+i);
}
NE=;
memset(head,-,sizeof(head));
for(int i=; i<n; ++i){
scanf("%d%d",&a,&b);
addEdge(a,b);
addEdge(b,a);
}
memset(vis,,sizeof(vis));
ansx=ansy=INF;
divide();
if(ansx==INF) puts("No solution");
else printf("%d %d\n",ansx,ansy);
}
return ;
}

HDU4812 D Tree(树的点分治)的更多相关文章

  1. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  2. 【poj1741】Tree 树的点分治

    题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...

  3. POJ1741——Tree(树的点分治)

    1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...

  4. hdu4812-D Tree (树的点分治)

    昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时.后来查出好多错= =比如v,u写倒了,比如+写成了取最值,比如....爆int...查了两个多小时的错..哭...(没想到进首页了 h ...

  5. 【POJ 1741】 Tree (树的点分治)

    Tree   Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...

  6. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

  7. HDU 4670 Cube number on a tree ( 树的点分治 )

    题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 ...

  8. poj 1741 Tree(树的点分治)

    poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...

  9. POJ 1741 Tree 树的分治(点分治)

    题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...

随机推荐

  1. (转载)解决ListView中使用EditText所遇到的一些冲突

    大家都知道在listView中使用editText,在输入过程中是有冲突的.今天稍微研究了一下这个问题,有一点点小小的心得和大家一起分享下. 首先建立一个最简单的demo,主界面就是一个ListVie ...

  2. django-cms 代码研究(三)插件(plugs in)

    插件(plugs in) djangocms支持的插件有: http://docs.django-cms.org/en/latest/basic_reference/plugin_reference. ...

  3. linux 下如何查看和踢除正在登陆的其它用户 ==>Linux下用于查看系统当前登录用户信息的4种方法

    在linux系统中用pkill命令踢出在线登录用户 由于linux服务器允许多用户登录,公司很多人知道密码,工作造成一定的障碍 所以需要有时踢出指定的用户 1/#who   查出当前有那些终端登录(用 ...

  4. 20个很有用的PHP类库

    介绍20个非常有用的PHP类库,相信一定可以为你的WEB开发提供更好和更为快速的方法. 图表库 下面的类库可以让你很简的创建复杂的图表和图片.当然,它们需要GD库的支持. pChart – 一个可以创 ...

  5. boa服务器make错误

    参考: http://zhouyang340.blog.163.com/blog/static/3024095920121187544204/ http://blog.csdn.net/hongjiu ...

  6. poj 1833

    http://poj.org/problem?id=1833 next_permutation这个函数是用来全排列的,按字典的序进行排列,当排列无后继的最大值时,会执行字典升序排列,相当于排序: 当排 ...

  7. 31.从尾到头输出链表[Print linked list from last to first]

    [题目] 输入一个链表的头结点,从尾到头反过来输出每个结点的值. [分析] 这是一道很有意思的面试题.该题以及它的变体经常出现在各大公司的面试.笔试题中. [链表逆置] 看到这道题后,第一反应是从头到 ...

  8. maven的一些依赖

    maven的一些依赖: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w ...

  9. (十)stm32中FSMC的使用(用于LCD)

    FSMC全称“静态存储器控制器”. 使用FSMC控制器后,可以把FSMC提供的FSMC_A[25:0]作为地址线,而把FSMC提供的FSMC_D[15:0]作为数据总线. (1)当存储数据设为8位时, ...

  10. .net学习笔记----会话状态Session

    一.会话状态Session Session用于服务器端状态管理,使用Session之后,每个客户端都可以将实际的数据保存在服务器上,对于每个客户端的数据,将会生成一个对应的唯一的key(保存在客户端) ...