树的直径(待补充)
模板 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;
}

浙公网安备 33010602011771号