Bob in Wonderland

题意:

一棵树,问最少移动多少次边可以使其变成一个链?
移动是指:从原位置拆下并连到新位置,这样算一次

题解:

错误思路

我一开始在想既然求最少移动次数,那我们就尽可能在原本的就存在的链的基础上进行修改,也就是先找树中最长的链(即树的直径),然后看这条链上有多少子链相连,拆下来再连上即可,所以先跑两边dfs,求出最长直径,并记录直径上的点,然后依次查看直径上的点的度数是否大于2,如果大于2就说明除了前后两个点,还有其他点相连,注意如果7连在6上,然后6连在直径上,那6和7是算一个整体的,所以只需要查看直径点的度数即可

正确思路

但是。。代码就是wa。。。感觉是两边dfs不对???
我也很懵逼,后来又想了想,其实完全没这么复杂,因为没有必要先求直径,我们直接求所有点的度数,然后查看度数是否大于等于2,并累加即可
而且,如果链的上面存在链怎么办?也就是7连着6,6连着5,5连着直径上一点,但是6还连接着其他链,这样我们只查看直径上的点就不对了,应该是查看所有度数大于2的点
先求树的直径纯属画蛇添足,因为如果所有点组成链,那么所有点的度数必然小于等于2(两端等于1,中间等于2),所以直接查看所有点度数就行

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=6e5+9;
vector<int>G[maxn];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        int w=G[i].size()-2;
        if(w>0)
        {
            sum+=w; 
        }
    }
    cout<<sum<<endl;
    return 0;
}