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;
    }
    

      

  • 相关阅读:
    Beginning iOS 8 Programming with Swift-TableView
    the-swift-programming-language 学习笔记
    Sharepoint 查阅项字段和计算值字段的定义
    java
    【转载】大型网站架构系列:消息队列(二)
    【转载】大型网站架构系列:分布式消息队列(一)
    【转载】高并发的核心技术-幂等的实现方案
    win2003 64位系统下ODBC连接使用
    PL/SQL Developer连接本地Oracle 11g 64位数据库
    Repeater 创建复杂表头的表格
  • 原文地址:https://www.cnblogs.com/Przz/p/5812341.html
Copyright © 2011-2022 走看看