zoukankan      html  css  js  c++  java
  • HDU 6430 Problem E. TeaTree(虚树)

    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
    ",answer[i]);
    164     return 0;
    165 }
    View Code
  • 相关阅读:
    “介绍一下自己吧”——记2020BUAA软工团队介绍和采访
    [no code][scrum meeting] Alpha 7
    [no code][scrum meeting] Alpha 6
    [no code][scrum meeting] Alpha 5
    [no code][scrum meeting] Alpha 4
    [no code][scrum meeting] Alpha 3
    [no code][scrum meeting] Alpha 2
    [no code][scrum meeting] Alpha 1
    [no_code]团队贡献分分配规则
    [no_code]团队任务拆解Alpha
  • 原文地址:https://www.cnblogs.com/xcantaloupe/p/9559640.html
Copyright © 2011-2022 走看看