CF1337C Linova and Kingdom(贪心)

牢记法则,正难则反

我刚开始考虑的是从深度深的地方开始算,但是发现,我们是越找深度越浅,但是深度深的答案会被深度浅的影响,这样思考起来很复杂。

因此如果能找到一个从上面往下找的方法就好了,所以考虑先把所有的都当作工业节点,然后转化n-k为旅游节点

首先,旅游节点肯定不是跳跃的,而是连续的,因此如果当前点不是旅游节点,他的儿子肯定也不可能是,这样想一想就能接受

当我们把一个工业节点转成旅游节点,那么他的贡献就是子树大小-到根的深度,因为原先是工业节点,如果考虑他是旅游节点,他的父亲都已经是旅游节点。因此本来可以增加他的祖先,现在没了

但是现在他的儿子可以通过他,因此就算出贡献度

之后排序即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
const int mod=1e9+7;
int h[N],ne[N],e[N],w[N],idx;
int son[N];
int d[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int u,int fa,int cur){
    int i;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa)
            continue;
        son[u]+=dfs(j,u,cur+1);
    }
    d[u]=son[u]-cur;
    return son[u]+1;
}
int main(){
    int n,k;
    cin>>n>>k;
    int i;
    vector<int> num;
    memset(h,-1,sizeof h);
    for(i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    dfs(1,-1,0);
    sort(d+1,d+1+n);
    reverse(d+1,d+1+n);
    ll ans=0;
    for(i=1;i<=n-k;i++){
        ans+=d[i];
    }
    cout<<ans<<endl;

}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12787358.html