Luogu P3408 Love

Topic links: the Click here Wallpaper

Solution:

Set f [x] represents the letter x to make the least money to spend to its parent, per [x] x number of people to write to make it at least to father

The \ (f [X] = \ sum_ {I} = ^ {per. 1 [X]} f [Son [X]] \) , at this time, f is from small to large arrays through sequence

Then we just need to put multiset son each point to maintain good, the final output f [0]

The total time complexity \ (O (n \, log \, n) \)

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+1;
const int inf=2147483647;
int n,m,t,cnt,head[N];
int ans,a[N],per[N],cost[N],num[N];
struct Edge{int nxt,to;}edge[N];
struct cmp{bool operator()(const int& a,const int& b)const{return cost[a]<cost[b];}};
multiset<int,cmp> q[N];
multiset<int,cmp>::iterator it;
void ins(int x,int y){
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;head[x]=cnt;
}
void dfs(int x){
    int flag=0;
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to;
        dfs(y);q[x].insert(y);
        flag=1;
    }
    if(!flag){cost[x]=a[x];return ;}
    if(x){
        int u=per[x];it=q[x].begin();
        for(int i=1;i<=u;i++){
            if(it==q[x].end()){
                cost[x]=inf;
                return ;
            }cost[x]+=cost[*it],++it;
        }
    }else{int w=(m*num[x]+t-1)/t;
        it=q[x].begin();
        for(int i=1;i<=w;i++)
            ans+=cost[*it],++it;
    }
}
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
signed main(){
    n=read(),t=read(),m=read();
    for(int i=1;i<=n;i++){
        int x=read(),y=read();
        ins(x,i);a[i]=y;num[x]++;
    }
    for(int i=1;i<=n;i++) per[i]=(num[i]*a[i]+t-1)/t;
    dfs(0);printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/NLDQY/p/11140874.html