bzoj 3573 [Hnoi2014]米特运输

http://www.elijahqi.win/archives/3732
Description
米特是D星球上一种非常神秘的物质,蕴含着巨大的能量。在以米特为主要能源的D星上,这种米特能源的运输和储
存一直是一个大问题。D星上有N个城市,我们将其顺序编号为1到N,1号城市为首都。这N个城市由N-1条单向高速
通道连接起来,构成一棵以1号城市(首部)为根的树,高速通道的方向由树中的儿子指向父亲。树按深度分层:
根结点深度为0,属于第1层;根结点的子节点深度为1,属于第2层;依此类推,深度为i的结点属于第i+l层。建好
高速通道之后,D星人开始考虑如何具体地储存和传输米特资源。由于发展程度不同,每个城市储存米特的能力不
尽相同,其中第i个城市建有一个容量为A[i]的米特储存器。这个米特储存器除了具有储存的功能,还具有自动收
集米特的能力。如果到了晚上六点,有某个储存器处于未满的状态,它就会自动收集大气中蕴含的米特能源,在早
上六点之前就能收集满;但是,只有在储存器完全空的状态下启动自动收集程序才是安全的,未满而又非空时启动
可能有安全隐患。早上六点到七点间,根节点城市(1号城市)会将其储存器里的米特消耗殆尽。根节点不会自动
搜集米特,它只接受子节点传输来的米特。早上七点,城市之间启动米特传输过程,传输过程逐层递进:先是第2
层节点城市向第1层(根节点城市,即1号城市)传输,直到第1层的储存器满或第2层的储存器全为空;然后是第3
层向第2层传输,直到对于第2层的每个节点,其储存器满或其予节点(位于第3层)的储存器全为空;依此类推,
直到最后一层传输完成。传输过程一定会在晚上六点前完成。
由于技术原因,运输方案需要满足以下条件:

(1)不能让某个储存器到了晚上六点传输结束时还处于非空但又未满的状态,这个时候储存器仍然会启动自动收集
米特的程序,而给已经储存有米特的储存器启动收集程序可能导致危险,也就是说要让储存器到了晚上六点时要么
空要么满;

(2)关于首都——即1号城市的特殊情况, 每天早上六点到七点间1号城市中的米特储存器里的米特会自动被消耗
殆尽,即运输方案不需要考虑首都的米特怎么运走;

(3)除了1号城市,每个节点必须在其子节点城市向它运输米特之前将这座城市的米特储存器中原本存有的米特全部
运出去给父节点,不允许储存器中残存的米特与外来的米特发生混合;

(4)运向某一个城市的若干个来源的米特数量必须完全相同,不然,这些来源不同的米特按不同比例混合之后可能
发生危险。
现在D星人已经建立好高速通道,每个城市也有了一定储存容量的米特储存器。为了满足上面的限制条件,可能需
要重建一些城市中的米特储存器。你可以,也只能,将某一座城市(包括首都)中屎来存在的米特储存器摧毁,再
新建一座任意容量的新的米特储存器,其容量可以是小数(在输入数据中,储存器原始容量是正整数,但重建后可
以是小数),不能是负数或零,使得需要被重建的米特储存器的数目尽量少。
Input
第一行是一个正整数N,表示城市的数目。接下来N行,每行一个正整数,其中的第i行表示第i个城市原来存在的米
特储存器的容量。再接下来是N-I行,每行两个正整数a,b表示城市b到城市a有一条高速通道(a≠b)。
N<500000,A[j]<10^8
Output
输出文件仅包含一行,一个整数,表示最少的被重建(即修改储存器容量)的米特储存器的数目。

Sample Input
5
5
4
3
2
1
1 2
1 3
2 4
2 5
Sample Output
3
HINT
【样例解释】

一个最优解是将A[1]改成8,A[3]改成4,A[5]改成2。这样,2和3运给1的量相等,4和5运给2的量相等,且每天晚上六点的时候,1,2满,3,4,5空,满足所有限制条件。

题意:不吐槽了

求每个节点的叶节点的值都恰好是父节点的度数分之一

即要求相同 且相加等于自己

那么前置技能log(x*y)=log(x)+log(y)

然后从1开始dfs求出每个节点按照他的深度什么换算 应该是到达1节点的i时候变成原来的多少倍 那么把所有数乘进去然后排序可得 求一下 最多的相同的数字有多少个 用总数减去即可
我思考了log(0)怎么办..菜

#include<cmath>
#include<cstdio>
#include<cctype>
#include<algorithm>
#define eps 1e-5
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int N=500050;
struct node{
    int y,next;
}data[N<<1];
int h[N],n,a[N],d[N],num;double s[N];
inline void dfs(int x,int fa){
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].y;if(y==fa) continue;
        s[y]=s[x]+log(d[x]);dfs(y,x);
    }
}
int main(){
    freopen("bzoj3573.in","r",stdin);
    n=read();
    for (int i=1;i<=n;++i) a[i]=read();
    for (int i=1;i<n;++i){
        int x=read(),y=read();++d[x];++d[y];
        data[++num].y=y;data[num].next=h[x];h[x]=num;
        data[++num].y=x;data[num].next=h[y];h[y]=num;
    }for (int i=2;i<=n;++i) --d[i];s[1]=log(1);dfs(1,0);
    for (int i=1;i<=n;++i) s[i]+=log(a[i]);
    sort(s+1,s+n+1);int ans=0,tmp=1;
    for (int i=1;i<=n;++i){
        if (fabs(s[i]-s[i-1])<eps) ++tmp,ans=max(ans,tmp);
        else tmp=1;
    }printf("%d\n",n-max(ans,tmp));
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值