悬关求调
查看原帖
悬关求调
352918
I_think_so_i_am_here楼主2024/5/1 19:14

首先 , 然后 , 其次 , 最后 。

思路大致是这样的,对于k$$=$$1的情况直接找出链然后 n$$*$$2$$-$$1$$-$$树的直径 就可以了。

对于k$$=$$2的情况。找一遍链上的点,然后找不属于链上的个节点的剩余链的长度中取最长的然后一减(n$$*$$2$$-$$树的直径$$-$$剩余最长链)就完事了。

以下是最后的代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,maxx[100010],maxx2[100010],maxxx,maxxxx,to1[100010],to2[100010],start;
vector<int>e[100010];
bool v[100010],huan[100010];
void maxlen(int x){
	v[x]=true;
	for(int p:e[x]){
		if(v[p])continue;
		maxlen(p);
		if(maxx[p]+1>maxx[x]){
			to2[x]=to1[x];
			maxx2[x]=maxx[x];
			to1[x]=p;
			maxx[x]=maxx[p]+1;
		}else if(maxx[p]+1>maxx2[x]){
			to2[x]=p;
			maxx2[x]=maxx[p]+1;
		}
	}
	if(maxxx<max(maxx[x],0)+max(maxx2[x],0)){
		maxxx=max(maxx[x],0)+max(maxx2[x],0);
		start=x;
	}
	return;
}
void find(int x){
	if(x==-1)return;
	huan[x]=true;
	find(to1[x]);
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++)to1[i]=-1,to2[i]=-1;
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	maxlen(1);
	if(k==1){
		cout<<2*n-1-maxxx<<endl;
		return 0;
	}
	find(to1[start]);
	find(to2[start]);
	for(int i=1;i<=n;i++){
		if(huan[i]){
			if(i==start){
				for(int p:e[i]){
					if(p==to1[i]||p==to2[i])continue;
					if(maxx[i]!=0)maxxxx=max(maxxxx,maxx[p]+1);
				}
			}else{
				if(maxx2[i]!=0)maxxxx=max(maxxxx,maxx2[i]+1);
			}
		}
	}
	cout<<2*n-maxxx-maxxxx<<endl;
    return 0;
}
2024/5/1 19:14
加载中...