Description
Explorer Bo likes exploring mazes around the world.Now he wants to explore a new maze.
The maze has N rooms connected with N−1 roads of length 1 so that the maze looks like a tree.
Explorer Bo can transfer to a room immediately or walk along a road which is not the one he walked just now.
Because the transfer costs too much, Mr Bo will minimum the transfer using times firstly.
Mr Bo wants to walk along all the roads at least once,but he is lazy and he wants to minimum the total length he walked.
Please help him!
Initial point can be arbitrarily selected
Solution
orz ShinFeb
这个问题比赛的时候想完了70%,剩下30%死也想不到了,orz ShinFeb大爷给出了一个超神的解决方案。
比赛的时候没做出来很愧疚啊。。感觉对不起大家
这题显然dp
那个瞬移次数是可以确定的,
=⌈叶子节点个数2⌉
(画个图就可以出来,因为一般情况下起点肯定是一个叶子节点,终点也是一个叶子节点)
对于一棵以
v
为根的子树,我们记其叶子节点个数为
考虑其一个子节点
to
如果
sz[to]≡0 mod 2
,那么
v
到
反之
v
到
那么可以直接dp解决。
然而如果叶子节点个数是奇数,那么有一段路径可以省掉,那咋办?
ShinFeb给了一个很好的方案
假设根节点是一个叶子节点。
我们先dp
然后考虑从根节点开始删除一段区间。
对于经过的点,只要把1反转成2,2反转成1即可。
然后求一下可以缩减的最大值即可
Code
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef vector<int> vec;
#define ph push
#define pb push_back
const int M=1e5+5;
vec G[M];
inline void Max(int &a,int b){
if(a<b)a=b;
}
inline void Min(int &a,int b){
if(a>b)a=b;
}
inline void rd(int &a){
a=0;char c;
while(c=getchar(),!isdigit(c));
do a=a*10+(c^48);
while(c=getchar(),isdigit(c));
}
ll dp[M];
int sz[M];
bool mark[M];
void dfs(int v,int f){
bool flag=0;
for(int i=0;i<G[v].size();++i){
int to=G[v][i];
if(to==f)continue;
dfs(to,v);
if(sz[to]&1)++dp[v];
else dp[v]+=2;
dp[v]+=dp[to];
sz[v]+=sz[to];
flag=1;
}
if(!flag)mark[v]=1,sz[v]=1;
}
int Mx=0;
inline void rdfs(int v,int f,int dlt){
Max(Mx,dlt);
for(int i=0;i<G[v].size();++i){
int to=G[v][i];
if(to^f)rdfs(to,v,dlt+(sz[to]&1?-1:1));
}
}
inline void gao(){
int n;cin>>n;
for(int i=1;i<=n;++i)G[i].clear();
memset(dp,0,sizeof(dp));
memset(sz,0,sizeof(sz));
Mx=0;
for(int i=1,a,b;i<n;++i){
rd(a),rd(b);
G[a].pb(b),G[b].pb(a);
}
int s;
for(int i=1;i<=n;++i)
if(G[i].size()==1)s=i;
dfs(s,s);
rdfs(s,s,0);
++sz[s];
if(sz[s]&1)cout<<dp[s]-Mx<<endl;
else cout<<dp[s]<<endl;
}
int main(){
int _;
for(cin>>_;_--;)gao();
return 0;
}