zoukankan      html  css  js  c++  java
  • hdu 4812 DTree (点分治)

    D Tree

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
    Total Submission(s): 3876    Accepted Submission(s): 743


    Problem Description
    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 106 + 3) equals to K?
    Can you help them in solving this problem?
     
    Input
    There are several test cases, please process till EOF.
    Each test case starts with a line containing two integers N(1 <= N <= 105) and K(0 <=K < 106 + 3). The following line contains n numbers vi(1 <= vi < 106 + 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.
     
    Output
    For 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
    /*
    hdu 4812 DTree (点分治)
    
    problem:
    求最小的点对使 u->v的点权的乘积%mod=limit.
    
    solve:
    每次求过当前树根节点的情况. 每次可以计算出 一点到当前根节点的情况temp,所以只需要找出其它子树中是否有limit/temp
    因为有取余,所以先预处理出所有的逆元.
    
    hhh-2016-08-23 10:52:26
    */
    #pragma comment(linker,"/STACK:124000000,124000000")
    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <math.h>
    #include <map>
    #define lson  i<<1
    #define rson  i<<1|1
    #define ll long long
    #define clr(a,b) memset(a,b,sizeof(a))
    #define key_val ch[ch[root][1]][0]
    #define inf 0x3FFFFFFFFFFFFFFFLL
    #define mod 1000003
    using namespace std;
    const int maxn = 100010;
    ll val[maxn],d[maxn],limit;
    int head[maxn];
    int n,k,s[maxn],f[maxn],root;
    int Size,tot;
    bool vis[maxn];
    vector<ll> ta;
    
    struct node
    {
        int to,w,next;
    }edge[maxn<<2];
    
    void add_edge(int u,int v)
    {
        edge[tot].to=v,edge[tot].next=head[u],head[u]=tot++;
    }
    
    void get_root(int now,int fa)
    {
        int v;
        s[now] = 1,f[now] = 0;
        for(int i = head[now];~i;i = edge[i].next)
        {
            if( (v=edge[i].to) == fa || vis[v])
                continue;
            get_root(v,now);
            s[now] += s[v];
            f[now] = max(f[now],s[v]);
        }
        f[now] = max(f[now],Size - s[now]);
        if(f[now] < f[root]) root = now;
    }
    int id[maxn];
    int idnum;
    void dfs(int now,int fa)
    {
        int v;
        ta.push_back(d[now]);
        id[idnum++] = now;
        s[now] = 1;
        for(int i = head[now];~i;i = edge[i].next)
        {
            if( (v=edge[i].to) == fa || vis[v])
                continue;
            d[v] =  (d[now] * val[v])%mod;
            dfs(v,now);
            s[now] += s[v];
        }
    }
    int flag[mod + 10];
    int mp[mod + 10];
    int cur = 0;
    ll ni[mod+10];
    int ans[2];
    void to_ans(int a, int b)
    {
    
        if (a > b) swap(a,b);
        if (ans[0] == -1 || ans[0] > a) ans[0] = a, ans[1] = b;
        else if (ans[0] == a && ans[1] > b) ans[1] = b;
    //    cout <<"a:"<<ans[0] << " b:" <<ans[1] <<endl;
    }
    
    void work(int now,int cnt)
    {
        f[0] = Size = cnt;
        get_root(now,root = 0);
        int v;
        vis[root] = 1;
        for(int i = head[root];~i;i = edge[i].next)
        {
            if(!vis[v = edge[i].to])
            {
                ta.clear(),d[v] = val[v],idnum = 0;
                dfs(v,0);
    
                for(int j = 0; j < ta.size();j++)
                {
                    if(val[root]*ta[j] % mod == limit && root != id[j])
                        to_ans(root,id[j]);
                    ll t = (ll)limit*ni[val[root]*ta[j]%mod]%mod;
                    if(flag[t] != cur)
                        continue;
                    if(mp[t] == id[j])
                        continue;
                    to_ans(mp[t],id[j]);
                }
                for(int j = 0; j < ta.size(); j++)
                {
                    int t = ta[j];
                    if(flag[t] != cur || mp[t] > id[j]) mp[t] = id[j],flag[t] = cur;
                }
            }
        }
        cur ++;
        for(int i = head[root];~i;i = edge[i].next)
        {
            if(vis[edge[i].to])
                continue;
            work(edge[i].to,s[edge[i].to]);
        }
    }
    
    ll egcd(ll a,ll b, ll &x, ll &y)
    {
        ll temp,tempx;
        if (b == 0)
        {
            x = 1;
            y = 0;
            return a;
        }
        temp = egcd(b,a % b, x, y);
        tempx = x;
        x = y;
        y = tempx - a / b * y;
        return temp;
    }
    
    int main()
    {
    
        ll y;
        for (int i = 0; i < mod; i++)
        {
            egcd(i*1ll, mod*1ll, ni[i], y);
            ni[i] %= mod, ni[i] = (ni[i]+mod)%mod;
        }
        while(scanf("%d%I64d",&n,&limit)!=EOF)
        {
            if(!n && !limit)
                break;
            clr(vis,0),clr(flag,0);
            clr(head,-1),tot = 0;
            ans[0] = ans[1] = -1;
            int a,b;
            for(int i = 1; i <= n; i++)
            {
                scanf("%I64d",&val[i]);
            }
            for(int i = 1; i < n; i++)
            {
                scanf("%d%d",&a,&b);
                add_edge(a,b);
                add_edge(b,a);
            }
            cur = 1;
            work(1,n);
            if(ans[0] == -1)
                printf("No solution
    ");
            else
                printf("%d %d
    ",ans[0],ans[1]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    写给自己:青年员工交流会会议记录
    写给自己:金融小白的考证之路
    写给自己:入职初体验
    反欺诈体系
    政策&定价&风控审批策略
    你还在寻找Navicat的破解版本?你应该了解开源免费的DBeaver
    规则引擎在IoT的重要性?
    轻松上手SpringBoot Security + JWT Hello World示例
    Kafka 系列-1
    JDK14-ZGC调研初探
  • 原文地址:https://www.cnblogs.com/Przz/p/5812341.html
Copyright © 2011-2022 走看看