树的直径(待补充)

模板 B4016 树的直径

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5; 
int n, p, dis[N];
vector<int> g[N];
inline int read(){
	int s=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+(c^48);c=getchar();}
	return s*f;
}
void dfs(int x, int fa){
	for(int i=0;i<g[x].size();i++){
		int t = g[x][i];
		if(t == fa)continue;
		dis[t] = dis[x] + 1;
		dfs(t, x);
	}
}
int main(){
	n = read();
	for(int i=1;i<n;i++){
		int u = read(), v = read();
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1, 0);
	p=1;
	for(int i=1;i<=n;i++)if(dis[p] < dis[i])p=i;
	memset(dis, 0, sizeof dis);
	dfs(p, 0);
	p=1;
	for(int i=1;i<=n;i++)if(dis[p] < dis[i])p=i;
	cout << dis[p];
	return 0;
}

\(\,\)

P5536 【XR-3】核心城市

找直径的中点,再转化成对每个点的 max_dep - dep 进行排序
一开始没想到,感觉自己对问题的转化解决能力还很差(准备再找点 树形dp 练练)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5; 
int n, k, p, dis[N], dep_max[N];
vector<int> g[N];
inline int read(){
	int s=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+(c^48);c=getchar();}
	return s*f;
}
void dfs(int x, int fa){
	dep_max[x] = dis[x];
	for(int i=0;i<g[x].size();i++){
		int t = g[x][i];
		if(t == fa)continue;
		dis[t] = dis[x] + 1;
		dfs(t, x);
		dep_max[x] = max(dep_max[x], dep_max[t]);
	}
}
int dfs_midpoint(int x){
	if(dis[x] <= (dis[p] >> 1))return x;
	for(int i=0;i<g[x].size();i++){
		int t = g[x][i];
		if(dis[t] < dis[x])return dfs_midpoint(t);
	}
}
int main(){
	n = read(), k = read();
	for(int i=1;i<n;i++){
		int u = read(), v = read();
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1, 0);
	p=1;
	for(int i=1;i<=n;i++)if(dis[p] < dis[i])p=i;
	memset(dis, 0, sizeof dis);
	dfs(p, 0);
	p=1;
	for(int i=1;i<=n;i++)if(dis[p] < dis[i])p=i;
	int midpoint = dfs_midpoint(p);
	memset(dis, 0, sizeof dis);
	memset(dep_max, 0, sizeof dep_max);
	dfs(midpoint, 0);
	for(int i=1;i<=n;i++)dis[i] = dep_max[i] - dis[i];
	sort(dis+1, dis+n+1);
	cout << dis[n-k] + 1;
	return 0;
}

\(\,\)

P1099 [NOIP 2007 提高组] 树网的核 / P2491 [SDOI2011] 消防

这题调了好久呀...
首先题目要求的是一条路径,我还以为和上面的核心城市一样,随便几个点就行呢
然后就是找树的中心的时候,有两个要注意的地方:

  • \(dis_x \le \frac{len}{2}\) 时,要比较一下是选 x 还是 fa
  • 没有考虑到边权可以为 \(0\) 呀,好可恶的题目,需要再记一个 \(dep\) ,回溯时用深度就好了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5+5; 
int n, k, p, f[N], up[N], du[N], dep[N], dis[N], dis_max[N];
struct Edge{
	int to, w;
};
struct Element{
	int dep, val, u, v;
	bool operator <(const Element &tmp){
		return dep > tmp.dep;
	}
}a[N];
vector<Edge> g[N];
inline int read(){
	int s=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+(c^48);c=getchar();}
	return s*f;
}
void dfs(int x, int fa){
	dis_max[x] = dis[x];
	for(int i=0;i<g[x].size();i++){
		int t = g[x][i].to;
		if(t == fa)continue;
		dis[t] = dis[x] + g[x][i].w;
		dep[t] = dep[x] + 1;
		up[t] = g[x][i].w;
		f[t] = x;
		dfs(t, x);
		dis_max[x] = max(dis_max[x], dis_max[t]);
	}
}
int dfs_midpoint(int x, int fa){
	if(dis[x] <= (dis[p] >> 1)){ //看看谁作为中心更合适 
		if(max(dis[x], dis_max[x]-dis[x]) < max(dis[fa], dis_max[fa] - dis[fa]))return x;
		return fa;
	}
	for(int i=0;i<g[x].size();i++){
		int t = g[x][i].to;
		if(dep[t] < dep[x])return dfs_midpoint(t, x);
	}
}
int main(){
	n = read(), k = read();
	for(int i=1;i<n;i++){
		int u = read(), v = read(), w = read();
		g[u].push_back(Edge{v, w});
		g[v].push_back(Edge{u, w});
	}
	dfs(1, 0);
	p=1;
	for(int i=1;i<=n;i++)if(dis[p] < dis[i])p=i;
	memset(dis, 0, sizeof dis);
	dfs(p, 0);
	p=1;
	for(int i=1;i<=n;i++)if(dis[p] < dis[i])p=i;
	int midpoint = dfs_midpoint(p, 0);
	memset(dis, 0, sizeof dis);
	memset(dis_max, 0, sizeof dis_max);
	memset(dep, 0, sizeof dep); 
	memset(up, 0, sizeof up);
	memset(f, 0, sizeof f);
	dfs(midpoint, 0);
	for(int i=1;i<=n;i++)a[i] = Element{dis_max[i] - dis[i] + up[i], up[i], i, f[i]};
	sort(a+1, a+n+1);
	for(int i=1;i<=n;i++){
		if(a[i].u == 0 || a[i].v == 0)continue;
		//一开始理解错题意了,它要求是一条路径 
		du[a[i].u]++;
		du[a[i].v]++;
		if(du[a[i].u] > 2 || du[a[i].v] > 2){
			cout << a[i].dep;
			break;
		}
		if(k >= a[i].val){
			k -= a[i].val;
		}else {
			cout << a[i].dep;
			break;
		}
	}
	return 0;
}
posted @ 2025-10-04 11:00  今添  阅读(6)  评论(0)    收藏  举报