码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 6430 Problem E. TeaTree(虚树)

时间:2018-08-30 14:23:47      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:dde   enc   turn   isp   lines   img   memset   ret   temp   

Problem E. TeaTree

Problem Description
Recently, TeaTree acquire new knoledge gcd (Greatest Common Divisor), now she want to test you.
As we know, TeaTree is a tree and her root is node 1, she have n nodes and n-1 edge, for each node i, it has it’s value v[i].
For every two nodes i and j (i is not equal to j), they will tell their Lowest Common Ancestors (LCA) a number : gcd(v[i],v[j]).
For each node, you have to calculate the max number that it heard. some definition:
In graph theory and computer science, the lowest common ancestor (LCA) of two nodes u and v in a tree is the lowest (deepest) node that has both u and v as descendants, where we define each node to be a descendant of itself.
Input
On the first line, there is a positive integer n, which describe the number of nodes.
Next line there are n-1 positive integers f[2] ,f[3], …, f[n], f[i] describe the father of node i on tree.
Next line there are n positive integers v[2] ,v[3], …, v[n], v[i] describe the value of node i.
n<=100000, f[i]<i, v[i]<=100000
Output
Your output should include n lines, for i-th line, output the max number that node i heard.
For the nodes who heard nothing, output -1.
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6430
题意:
一棵树上每个节点权值为v[i],每个节点的heard值是:以它为LCA的两个节点的GCD的最大值,要求输出每个节点的heard值。
树节点个数1e5,权值为最大1e5。
思路:由于权值最大才1e5,开一个1e5的vector,考虑将树节点存入它权值因子的vector(比如权值为9的结点,将他存入v[1],v[3],v[9]里),然后按照每一个vector建立一棵虚树。将这颗虚树上除了叶子的点的答案都更新。但是由于只要更新非叶子节点的值,我就直接在建立虚树边的时候更新了,省去建边和搜索的过程。
技术分享图片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<cmath>
  6 using namespace std;
  7 const int maxn = 100500;
  8 
  9 struct Edge       ///存原树
 10 {
 11     int to,next;
 12 } E[maxn << 1];
 13 int frist[maxn], sign = 1;
 14 inline void AddEdge(int u, int v)
 15 {
 16     E[sign].to = v;
 17     E[sign].next = frist[u];
 18     frist[u] = sign++;
 19 }
 20 
 21 /*
 22 struct void_tree  ///存虚树
 23 {
 24     int to,next;
 25 }vtree[maxn];
 26 int sign2=0,first2[maxn];
 27 inline void add_edge(int u, int v)
 28 {
 29     vtree[sign2].to = v;
 30     vtree[sign2].next = first2[u];
 31     first2[u] = sign2++;
 32 }
 33 */
 34 int dfn[maxn];   ///dfs序
 35 int deep[maxn];  ///节点深度
 36 int s[maxn];     ///
 37 int a[maxn];     ///存需要建立虚树的点
 38 int index=0;
 39 int top;         ///栈顶
 40 
 41 int fa[18][maxn];
 42 
 43 void dfs(int u)  ///预处理dep和fa[0][j]
 44 {
 45     dfn[u] = ++index;
 46     for(int i=frist[u];i;i=E[i].next)
 47     {
 48         if(E[i].to!=fa[0][u])
 49         {
 50             deep[E[i].to]=deep[u]+1;
 51             fa[0][E[i].to]=u;
 52             dfs(E[i].to);
 53         }
 54     }
 55 }
 56 inline int LCA(int u,int v)  ///求LCA
 57 {
 58     if(deep[u]>deep[v])swap(u,v);
 59     for(int i=16;~i;i--)
 60         if(deep[fa[i][v]]>=deep[u])
 61             v=fa[i][v];
 62     if(u==v)return u;
 63     for(int i=16;~i;i--)
 64         if(fa[i][u]!=fa[i][v])
 65         {
 66             u=fa[i][u];
 67             v=fa[i][v];
 68         }
 69     return fa[0][u];
 70 }
 71 int answer[maxn];
 72 
 73 inline void insert_point(int x,int num)  ///建立虚树
 74 {
 75     if(top == 0)
 76     {
 77         s[++top] = x;
 78         return ;
 79     }
 80     int lca = LCA(x, s[top]);
 81     if(lca == s[top])
 82     {
 83         s[++top]=x;
 84         return ;
 85     }
 86     while(top >= 1 && dfn[s[top - 1]] >= dfn[lca])
 87     {
 88         answer[s[top - 1]]=num;  ///不建边了,直接更新答案
 89         //add_edge(s[top - 1], s[top]);
 90         top--;
 91     }
 92     if(lca != s[top])
 93     {
 94         answer[lca]=num;
 95         //add_edge(lca, s[top]);
 96         s[top] = lca;
 97     }
 98     s[++top] = x;
 99 }
100 
101 inline int comp(const int &a, const int &b)
102 {
103     return dfn[a] < dfn[b];
104 }
105 
106 vector<int>mmp[maxn];
107 
108 int main()
109 {
110     int n,x,m;
111     memset(answer,-1, sizeof(answer));
112     memset(frist, -1, sizeof(frist));
113     scanf("%d",&n);
114     for(int i=2; i<=n; i++)
115     {
116         scanf("%d",&x);
117         AddEdge(x,i);
118     }
119 
120     deep[1]=fa[0][1]=1;
121     dfs(1);
122     for(int i=1;i<=17;i++)
123         for(int j=1;j<=n;j++)
124             fa[i][j]=fa[i-1][fa[i-1][j]];
125 
126     ///将节点存入它权值因子的vector
127     int Max = 0;
128     for(int i=1; i<=n; i++)
129     {
130         scanf("%d",&x);
131         Max = max(Max,x);
132         int temp = sqrt(x+1);
133         for(int j=1; j<=temp; j++)
134         {
135             if(x%j==0)
136             {
137                 mmp[j].push_back(i);
138                 if(j!=x/j)
139                     mmp[x/j].push_back(i);
140             }
141         }
142     }
143 
144     for(int k=1; k<=Max; k++)
145     {
146         m = mmp[k].size();
147         if(m<=1)continue;
148         for(int i = 1; i <= m; i++)a[i] = mmp[k][i-1];
149         sort(a + 1, a + m + 1, comp);
150         //memset(first2,-1,sizeof(first2));
151         top=0;
152         for(int i = 1; i <= m; i++)
153             insert_point(a[i],k);
154         while(top > 1)
155         {
156             answer[s[top - 1]]=k;           ///不建边了,直接更新答案
157             //add_edge(s[top - 1], s[top]);
158             top--;
159         }
160         //dfs(s[top]);                      ///省去dfs
161     }
162     for(int i=1;i<=n;i++)
163         printf("%d\n",answer[i]);
164     return 0;
165 }
View Code

 

HDU 6430 Problem E. TeaTree(虚树)

标签:dde   enc   turn   isp   lines   img   memset   ret   temp   

原文地址:https://www.cnblogs.com/xcantaloupe/p/9559640.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!