• HDU4812 D Tree


    There is a skyscraping tree standing on the playground of Nanjing University of Science and Technology. On each branch of the tree is an integer (The tree can be treated as a connected graph with N vertices, while each branch can be treated as a vertex). Today the students under the tree are considering a problem: Can we find such a chain on the tree so that the multiplication of all integers on the chain (mod 10 6 + 3) equals to K? 
    Can you help them in solving this problem?

    InputThere are several test cases, please process till EOF. 
    Each test case starts with a line containing two integers N(1 <= N <= 10 5) and K(0 <=K < 10 6 + 3). The following line contains n numbers v i(1 <= v i < 10 6 + 3), where vi indicates the integer on vertex i. Then follows N - 1 lines. Each line contains two integers x and y, representing an undirected edge between vertex x and vertex y.OutputFor each test case, print a single line containing two integers a and b (where a < b), representing the two endpoints of the chain. If multiply solutions exist, please print the lexicographically smallest one. In case no solution exists, print “No solution”(without quotes) instead. 
    For more information, please refer to the Sample Output below.Sample Input

    5 60
    2 5 2 3 3
    1 2
    1 3
    2 4
    2 5
    5 2
    2 5 2 3 3
    1 2
    1 3
    2 4
    2 5

    Sample Output

    3 4
    No solution
    
    
            
     

    Hint

     
    1. “please print the lexicographically smallest one.”是指: 先按照第一个数字的大小进行比较,若第一个数字大小相同,则按照第二个数字大小进行比较,依次类推。 2. 若出现栈溢出,推荐使用C++语言提交,并通过以下方式扩栈: #pragma comment(linker,"/STACK:102400000,102400000")

    树 点分治

      自己想到了点分治,自己想到了逆元,自己想到了更新答案的方法,然后TLE到飞起,去看了别人的题解才发现没有初始化邻接表,真是感人至深。

    其实就是个比较普通的点分治,把已经处理的链的结果存到map里(直接用数组就好),在处理新结点的时候匹配map里的值。

    需要注意的是在mod意义下找乘积为K的点,需要求逆元。逆元递推式见代码

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 #include<map>
      9 #define LL long long
     10 using namespace std;
     11 const int mod=1e6+3;
     12 const int mxn=120010;
     13 int read(){
     14     int x=0,f=1;char ch=getchar();
     15     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     16     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 struct edge{int v,nxt;}e[mxn<<1];
     20 int hd[mxn],mct=0;
     21 void add_edge(int u,int v){e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;}
     22 int n,K;
     23 LL w[mxn];
     24 //
     25 int mc[mxn],sz[mxn],rt,smm;
     26 LL dis[mxn];
     27 bool vis[mxn];
     28 //map<int,int>mp;
     29 int mp[mxn*11];
     30 //
     31 LL inv[mxn*11];
     32 void init(){
     33     inv[1]=1;
     34     for(int i=2;i<mod;i++){
     35         inv[i]=((-mod/i)*inv[mod%i]%mod+mod)%mod;
     36     }
     37     return;
     38 }
     39 void DFS_sz(int u,int fa){
     40     sz[u]=1;mc[u]=0;
     41     for(int i=hd[u];i;i=e[i].nxt){
     42         if(e[i].v==fa || vis[e[i].v])continue;
     43         int v=e[i].v;
     44         DFS_sz(v,u);
     45         sz[u]+=sz[v];
     46         mc[u]=max(mc[u],sz[v]);
     47     }
     48     mc[u]=max(mc[u],smm-mc[u]);
     49     if(mc[u]<mc[rt])rt=u;
     50     return;
     51 }
     52 int st[mxn],top=0;
     53 int ans[2];
     54 inline void upd(int x,int y){
     55     if(x>y)swap(x,y);
     56     if(!ans[0] || ans[0]>x || (ans[0]==x && ans[1]>y)){
     57         ans[0]=x;ans[1]=y;
     58     }
     59     return;
     60 }
     61 void clc(int u,int fa,int mode){
     62     if(!mode){    
     63         LL tmp=(K*inv[dis[u]]%mod+mod)%mod;
     64         if(mp[tmp]){    upd(u,mp[tmp]);    }
     65     }
     66     else{
     67         if(!mp[dis[u]]){mp[dis[u]]=u;st[++top]=dis[u];}
     68         else mp[dis[u]]=min(mp[dis[u]],u);
     69     }
     70     for(int i=hd[u];i;i=e[i].nxt){
     71         if(e[i].v==fa || vis[e[i].v])continue;
     72         int v=e[i].v;
     73         dis[v]=dis[u]*w[v]%mod;
     74         clc(v,u,mode);
     75     }
     76     return;
     77 }
     78 void solve(int x){
     79     vis[x]=1;
     80     mp[w[x]]=x;
     81     for(int i=hd[x];i;i=e[i].nxt){
     82         if(vis[e[i].v])continue;
     83         int v=e[i].v;
     84         dis[v]=w[v]%mod;
     85         clc(v,x,0);
     86         dis[v]=w[x]*w[v]%mod;
     87         clc(v,x,1);
     88     }
     89     while(top){
     90         mp[st[top--]]=0;
     91     }
     92     mp[w[x]]=0;
     93     for(int i=hd[x];i;i=e[i].nxt){
     94         if(vis[e[i].v])continue;int v=e[i].v;
     95         smm=sz[v];
     96         rt=0;
     97         DFS_sz(v,0);
     98         solve(rt);
     99     }
    100     return;
    101 }
    102 int main(){
    103     int i,j,u,v;
    104     init();
    105     while(scanf("%d%d",&n,&K)!=EOF){
    106         memset(hd,0,sizeof hd);mct=0;
    107         memset(vis,0,sizeof vis);
    108         ans[0]=ans[1]=0;
    109         for(i=1;i<=n;i++)w[i]=read();
    110         for(i=1;i<n;i++){
    111             u=read();v=read();
    112             add_edge(u,v);
    113             add_edge(v,u);
    114         }
    115         ans[0]=ans[1]=0;
    116         smm=n;mc[rt=0]=mod;
    117         DFS_sz(1,0);
    118         solve(rt);
    119         if(!ans[0])printf("No solution
    ");
    120         else printf("%d %d
    ",ans[0],ans[1]);
    121     }
    122     return 0;
    123 }
    本文为博主原创文章,转载请注明出处。
  • 相关阅读:
    高阶函数 练习
    斐波那契数列(Fibonacci sequence)递归函数
    顺序循环队列的基本操作(二)
    顺序循环队列基本操作(一)
    顺序栈的基本操作
    双链表的插入删除
    头插法实现链表逆置
    带头结点单链表的基本操作
    顺序表基本操作
    实现原数组列变成行,再将每一行首尾倒置
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6502460.html
Copyright © 2020-2023  润新知