zoukankan      html  css  js  c++  java
  • bzoj3573: [Hnoi2014]米特运输

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3573

    思路:语文题...

    正常题意:

    给定一棵树和每个点的权值,问最少改动多少个点的权值使得:

    1.每个点的所有儿子权值相等

    2.每个点的权值等于所有儿子权值和


    既然有这两个条件,那我们确定一个点的权值就确定了整棵树所有点的权值。

    枚举每个点不变,算出根节点的权值,选出现次数最多的方案,那么改动的点数就是n-方案数,此时最小

    因为根节点权值很大,取log或hash即可。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=500010,maxm=1000010;
    const double eps=1e-7;
    using namespace std;
    int n,a[maxn],pre[maxm],now[maxn],son[maxm],cnt[maxn],fa[maxn],val[maxn],res,tot;double s[maxn],ans[maxn];
    void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
    void dfs1(int x){for (int y=now[x];y;y=pre[y]) if (fa[x]!=son[y]) cnt[x]++,fa[son[y]]=x,dfs1(son[y]);}
    void dfs2(int x){
    	for (int y=now[x];y;y=pre[y]) if (son[y]!=fa[x])
    		s[son[y]]=s[x]+log(cnt[x]),dfs2(son[y]);
    }
    
    int main(){
    	scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&val[i]);
    	for (int i=1,a,b;i<n;i++) scanf("%d%d",&a,&b),add(a,b),add(b,a);
    	dfs1(1),s[1]=log(1.0),dfs2(1);
    	for (int i=1;i<=n;i++) ans[i]=s[i]+log(val[i]);
    	sort(ans+1,ans+1+n);
    	int cnt=0;
    	for (int i=1;i<=n;i++){
    		if (fabs(ans[i]-ans[i-1])<eps) cnt++;
    		else res=max(res,cnt),cnt=1;
    	}
    	res=max(res,cnt),printf("%d
    ",n-res);
    	return 0;
    }


  • 相关阅读:
    groovy脚本语言基础1
    014.Ansible Playbook Role 及调试
    013.Ansible Playbook include
    012.Ansible高级特性
    011.Ansible条件语句
    010.Ansible_palybook 循环语句
    009.Ansible模板管理 Jinja2
    008.Ansible文件管理模块
    007.Ansible变量Fact,魔法变量和lookup生成变量
    006.Ansible自定义变量
  • 原文地址:https://www.cnblogs.com/thythy/p/5493490.html
Copyright © 2011-2022 走看看