zoukankan      html  css  js  c++  java
  • 【bzoj 3252】攻略

    题意

    我们想到一个贪心,就是每次找到根路径前缀和最大的一个点,取走这条路径,同时把这条路径上的点权变成(0)

    正确性显然

    进一步发现我们需要从树上选择(m)条链使得链的总和最大

    于是我们考虑换上长链剖分,长儿子定义为往下走点权最大的儿子,每次把最长的路径取走就好了

    来一个堆维护一下就好了

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define re register
    #define LL long long
    #define mp std::make_pair
    typedef std::pair<LL,int> pii;
    const int maxn=200006;
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||x>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    std::priority_queue<pii> q;
    struct E{int v,nxt;}e[maxn];
    int head[maxn],a[maxn],son[maxn],vis[maxn];LL len[maxn];
    int n,m,num;
    inline void add(int x,int y) {
    	e[++num].v=y;e[num].nxt=head[x];head[x]=num;
    }
    void dfs1(int x) {
    	for(re int i=head[x];i;i=e[i].nxt) {
    		dfs1(e[i].v);
    		if(len[e[i].v]>len[son[x]]) son[x]=e[i].v;
    	}
    	len[x]=len[son[x]]+a[x];
    }
    int main() {
    	n=read(),m=read();
    	for(re int i=1;i<=n;i++) a[i]=read();
    	for(re int x,y,i=1;i<n;i++) {
    		x=read(),y=read(),add(x,y);
    	}
    	dfs1(1);
    	for(re int i=1;i<=n;i++) q.push(mp(len[i],i));
    	int tot=0;LL ans=0;
    	while(tot<m) {
    		int k=q.top().second;q.pop();
    		if(vis[k]) continue;
    		ans+=len[k];tot++;
    		while(k&&!vis[k]) vis[k]=1,k=son[k];
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Android 通过外键连接两个数据库
    WustOJ 1575 Gingers and Mints(快速幂 + dfs )
    Android数据库信息显示在listview上
    Android 开机启动通知
    JAVA车票管理系统(简单GUI)
    POJ1159 Palindrome(数位DP)
    python之Memcached 安装及操作
    Django中的缓存
    VUE 框架
    flask----flask-session
  • 原文地址:https://www.cnblogs.com/asuldb/p/10679293.html
Copyright © 2011-2022 走看看