求助#5错了,思路正确,样例过了
查看原帖
求助#5错了,思路正确,样例过了
750803
_Revenge_楼主2022/7/26 11:34

我想到的是贪心的策略,优先队列存储的是孩子个数(包括自己),队顶是最多的,这样贡献最多,按理来说是正确的

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef double db;

const int N=2e5+50;
const int M=1e5+50;
const int Mod=1e9+7;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

int n,k;
vector<int>tree[N];

struct node{
	int vol;
	int pos;
	int fa;
	bool operator <(const node &x)const{
		return x.vol>vol;
	}
};

priority_queue<node>q;
int f[N],siz[N];
void dfs(int ch,int p){
	int res=0;
//	if(tree[ch].size()==1&&p!=0) res=1;
	for(int i=0;i<tree[ch].size();++i){
		if(tree[ch][i]==p) continue;
		dfs(tree[ch][i],ch);
		res+=f[tree[ch][i]]+1;
	}
	f[ch]=res;
}
int main()
{
	n=read(),k=read();
	for(int i=1;i<n;++i){
		int u,v;
		u=read(),v=read();
		tree[u].push_back(v);
		tree[v].push_back(u);
	}
	if(k==0) {
		printf("0");
		return 0;
	}
	dfs(1,0);
//	cout<<f[1];
	for(int i=1;i<=n;++i) ++f[i];
//	k--;
	memset(siz,0,sizeof(siz));
	ll ans=0;
	q.push((node){f[1],1,0});
	k=n-k;
	while(k){
		node tmp=q.top();
		q.pop();
//		ans+=tmp-1;
		ans-=siz[tmp.pos];
		ans+=tmp.vol-1;
//		printf("%d\n",ans);
		for(int i=0;i<tree[tmp.pos].size();++i){
			if(tree[tmp.pos][i]==tmp.fa) continue;
			siz[tree[tmp.pos][i]]=siz[tmp.pos]+1;
			q.push((node){f[tree[tmp.pos][i]],tree[tmp.pos][i],tmp.pos});
		}
		--k;
	}
	printf("%lld\n",ans);
	return 0;
}

2022/7/26 11:34
加载中...