zoukankan      html  css  js  c++  java
  • hdoj4812 D Tree(点分治)

    题目链接:https://vjudge.net/problem/HDU-4812

    题意:给定一颗带点权的树,求是否存在一条路经的上点的权值积取模后等于k,如果存在多组点对,输出字典序最小的。

    思路:

      点分治模板题。按照套路,找重心,求出子树中节点到重心的权值积取模后的值dis[i](包括重心的权值,也不可以不包括,一样的),用id[j]记录该路径的端点,用的是点分治的第二种写法。递归时,用桶mine[i]记录到重心权值积为i的最小编号。然后查找时,对dis[j],满足要求的tmp为:tmp*dis[j]%MOD=k*V[u],因为我们的dis中包括重心的权值,所以重心的权值被乘了2次。然后用到了逆元,tmp=k*V[u]%MOD*inv[dis[j]]%MOD。更新完答案后就更新桶。

      因为没看清题目,题目求得点对(a,b)是a<b,而我以为(a,a)也满足,然后就找了两小时bug,崩溃到想锤电脑QAQ...。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    using namespace std;
    
    inline int read(){
        int x=0,f=0;char ch=0;
        while(!isdigit(ch)) {f|=ch=='-';ch=getchar();}
        while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return f?-x:x;
    }
    
    typedef long long LL;
    const int maxn=1e5+5;
    const int MOD=1e6+3;
    const int maxk=1e6+5;
    const int inf=0x3f3f3f3f;
    struct node1{
        int v,nex;
    }edge[maxn<<1];
    
    struct node2{
        int x,y;
        node2(){x=y=0;}
        node2(int x,int y):x(x),y(y){}
    }ans;
    
    bool operator < (node2 a,node2 b){
        if(a.x==b.x) return a.y<b.y;
        return a.x<b.x;
    }
    
    int n,k,cnt,head[maxn],sz[maxn],mson[maxn],Min,root,size;
    int vis[maxn],mine[maxk],id[maxn],t,tt;
    LL V[maxn],dis[maxn],inv[maxk];
    
    void init(){
        inv[1]=1;
        for(int i=2;i<maxk;++i)
            inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
    }
    
    void adde(int u,int v){
        edge[++cnt].v=v;
        edge[cnt].nex=head[u];
        head[u]=cnt;
    }
    
    void getroot(int u,int fa){
        sz[u]=1,mson[u]=0;
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(vis[v]||v==fa) continue;
            getroot(v,u);
            sz[u]+=sz[v];
            mson[u]=max(mson[u],sz[v]);
        }
        mson[u]=max(mson[u],size-sz[u]);
        if(mson[u]<Min) Min=mson[u],root=u;
    }
    
    void getdis(int u,int fa,LL len){
        dis[++t]=len,id[t]=u;
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(vis[v]||v==fa) continue;
            getdis(v,u,len*V[v]%MOD);
        }
    }
    
    void solve(int u){
        mine[V[u]]=u,t=0;
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(vis[v]) continue;
            tt=t;
            getdis(v,u,V[u]*V[v]%MOD);
            for(int j=tt+1;j<=t;++j){    
                LL tmp=1LL*k*V[u]%MOD*inv[dis[j]]%MOD;
                if(mine[tmp]==inf) continue;
                node2 other;
                if(mine[tmp]<id[j]) other.x=mine[tmp],other.y=id[j];
                else other.x=id[j],other.y=mine[tmp];
                if(other<ans) ans=other;
            }
            for(int j=tt+1;j<=t;++j)
                mine[dis[j]]=min(mine[dis[j]],id[j]);
        }
        mine[V[u]]=inf;
        for(int i=1;i<=t;++i)
            mine[dis[i]]=inf;
    }
    
    void fenzhi(int u,int ssize){
        vis[u]=1;
        solve(u);
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(vis[v]) continue;
            Min=inf,root=0;
            size=sz[v]<sz[u]?sz[v]:(ssize-sz[u]);
            getroot(v,0);
            fenzhi(root,size);
        }
    }
    
    int main(){
        init();
        memset(mine,0x3f,sizeof(mine));
        while(~scanf("%d%d",&n,&k)){
            cnt=0;
            ans.x=ans.y=n+1;
            for(int i=0;i<=n;++i)
                head[i]=vis[i]=0;
            for(int i=1;i<=n;++i){
                int tmp=read();
                V[i]=tmp;
            }
            for(int i=1;i<n;++i){
                int u=read(),v=read();
                adde(u,v);
                adde(v,u);
            }
            Min=inf,root=0,size=n;
            getroot(1,0);
            fenzhi(root,n);
            if(ans.x==n+1)
                printf("No solution
    ");
            else
                printf("%d %d
    ",ans.x,ans.y);
        }
        return 0;
    }
  • 相关阅读:
    VC CUtilityLZW 效率还行的LZW压缩算法,随机数加密
    VC CQHashNTBuffer 牛逼的Hash表 UINT32
    VC CHashBuffer 牛逼的hash表算法,字符串查找块了100倍
    关闭Fedora防火墙
    gnome 屏幕截图
    zynq -- arm-xilinx-eabi-路径
    Fedora 14安装出现的错误
    fedora19安装后,需要安装的一些必备的软件包
    zynq -- cannot find -lxil
    Zynq -- 启动过程
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11391489.html
Copyright © 2011-2022 走看看