HDU - 5102

题目链接:HDU - 5102


本来想直接点分治的。但是因为K很小,所以我们可以直接拓展。先用一条边,然后由一条边拓展到两条。

因为我们是单向拓展的,所以有些会拓展不到,所以我们对一条边弄两个方向,最后除以2即可。

点分治的话,就统计每个长度的次数,然后从小往大扫即可。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
const int N=1e5+10;
int n,k,cnt; long long res;
vector<int> g[N];
struct node{int u,fa,w;};
void solve(){
	cin>>n>>k; queue<node> q; res=0; k*=2;
	while(q.size())	q.pop();
	for(int i=1;i<=n;i++)	g[i].clear();
	for(int i=1,a,b;i<n;i++) 
		scanf("%d %d",&a,&b),q.push({a,b,1}),q.push({b,a,1}),
		g[a].push_back(b),g[b].push_back(a);
	cnt=n-1;
	for(int i=1;i<=k;i++){
		assert(q.size());
		node u=q.front(); q.pop(); res+=u.w;
		if(cnt<k){
			for(int to:g[u.u]) if(to!=u.fa) q.push({to,u.u,u.w+1}),cnt++;
		}		
	}
	cout<<res/2<<'\n';
}
signed main(){
	int T; cin>>T; while(T--) solve();
	return 0;
}

你可能感兴趣的:(思维题,HDU)