先贴码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n,k;
int dis1[maxn],dis2[maxn],max_d,dis[maxn];
int poi1[maxn],poi2[maxn],poi_check,max_d2;
bool if_maxd[maxn];
vector <int> edge[maxn];
void dfs(int u,int fa)
{
for (int i = 0;i < edge[u].size();i++)
{
int v = edge[u][i];
if (v == fa) continue;
dfs(v,u);
int t = dis1[v] + 1;
if (t > dis1[u])
dis2[u] = dis1[u],poi2[u] = poi1[u],dis1[u] = t,poi1[u] = v;
else if (t > dis2[u])
dis2[u] = t,poi2[u] = v;
// cout << u << "kkksc" << poi1[u] << "kkksc" << poi2[u] << endl;
}
if (dis1[u] + dis2[u] > max_d)
max_d = dis1[u] + dis2[u],poi_check = u;
}
void dfs1(int u,int fa)
{
for (int i = 0;i < edge[u].size();i++)
{
int v = edge[u][i];
if (v == fa) continue;
dfs1(v,u);
int size = 1;
if (if_maxd[v] and if_maxd[u]) size = -1;
max_d2 = max(max_d2,dis[u] + dis[v] + size);
dis[u] = max(dis[u],dis[v] + size);
}
}
int main()
{
cin >> n >> k;
for (int i = 1;i < n;i++)
{
int u,v;
cin >> u >> v;
edge[u].push_back(v),edge[v].push_back(u);
}
dfs(1,0);
if (k == 1)
cout << 2 * (n - 1) - max_d + 1;
else
{
for (int i = poi_check;i;i = poi1[i])
if_maxd[i] = 1;
for (int i = poi2[poi_check];i;i = poi1[i])
if_maxd[i] = 1;
dfs1(1,0);
cout << 2 * n - max_d - max_d2;
}
return 0;
}
在最后标记第一次直径的时候,我一开始是这么打的:
for (int i = poi_check;i;i = poi1[i])
if_maxd[i] = 1;
for (int i = poi_check;i;i = poi2[i])
if_maxd[i] = 1;
直接强行记录根的次长路的所有顶点而不是从根的次长路代表的节点的最长的