• 【洛谷3237】[HNOI2014] 米特运输(哈希)


    点此看题面

    • 给定一棵树,每个数有一个点权。
    • 问最少修改多少点权(可以改为小数),使得:
      • 同一节点各叶节点权值相同。
      • 一个节点的权值等于各叶节点权值之和。
    • (nle5 imes10^5)

    哈希

    考虑根据题目中给出的性质,确定一个点权实际上就确定了整棵树。

    于是我们求出每个点保持其权值不变时根节点的权值。

    如果若干点权值不变时根节点权值相同,它们就可以一起保留。

    哈希一下就好了。

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 500000 
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    #define mp make_pair
    #define fi first
    #define se second
    #define X1 20050413 
    #define X2 20201024
    using namespace std;
    int n,a[N+5],ee,lnk[N+5];struct edge {int to,nxt;}e[N<<1];
    map<pair<int,int>,int> p;int ans;
    I void dfs(CI x,CI lst,pair<int,int> o)//直接用pair来哈希
    {
    	ans=max(ans,++p[mp(1LL*o.fi*a[x]%X1,1LL*o.se*a[x]%X2)]);//统计最大的相同哈希值数
    	RI i,t=0;for(i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&++t;o=mp(1LL*o.fi*t%X1,1LL*o.se*t%X2);//统计子节点个数,以得出当前点和子节点权值倍数关系
    	for(i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(dfs(e[i].to,x,o),0);//递归
    }
    int main()
    {
    	RI i;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i);
    	RI x,y;for(i=1;i^n;++i) scanf("%d%d",&x,&y),add(x,y),add(y,x);
    	return dfs(1,0,mp(1,1)),printf("%d
    ",n-ans),0;//答案为总点数减去最大保留点数
    }
    
  • 相关阅读:
    性能测试系列七 工具选择
    Selenium Web自动化面试题总结(下篇)
    性能测试系列六 评估压测量
    hexo 安装
    光纤收发器组网方式
    频谱仪
    交换机网管telent
    区块链共识机制
    SDH、MSTP、OTN和PTN
    ACL知识
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3237.html
Copyright © 2020-2023  润新知