HDU 4607 Park Visit
Meaning of the questions: an N-node tree without roots, we have to visit the K-point, ask how much is the minimum path.
Solution: We set tree diameter dia, passing over the number of nodes num diameter
-
When <When K = num, ans = K-1. (Away from the one end along a diameter of the diameter)
-
others, ans = dia + (K - num) * 2 (diameter must be completed, but also to take the branch diameter, and the branch is to take repeated, i.e. twice)
For chestnut !!!
If K == 8
If K == 9
The very beginning is not clear K> num when in the end is what ghost formula, but the fact is draw a map to understand. Haha! !
Seek diameter of the tree
First, practice twice dfs
-
In any one of the root node, the root of the tree into non-rooted tree, find its maximum distance, and reaches the node is referred nod1.
-
In nod1 root, DFS running, find its maximum distance, to reach the node nod2. Dia is the distance between the two apparent nod1 and nod2 nodes.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e5 + 5;
int N, Q, k;
int head[maxN], cnt;
struct EDGE{
int adj, to;
EDGE(int a = -1, int b = 0): adj(a), to(b) {}
}edge[maxN << 1];
void add_edge(int u, int v)
{
edge[cnt] = EDGE(head[u], v);
head[u] = cnt ++;
}
struct DIA{
int nod1, nod2, dia;
DIA(int a = 0, int b = 0, int c = 0): nod1(a), nod2(b), dia(c) {}
}info;
void init()
{
memset(head, -1, sizeof(head));
cnt = 0;
info = DIA(0, 0, 0);
}
int dis[maxN];
void dfs(int x, int fa, int d, int flag)
{
dis[x] = d;
if(info.dia < dis[x])
{
info.dia = dis[x];
if(flag == 0)
info.nod1 = x;
else if(flag == 1)
info.nod2 = x;
}
for(int i = head[x]; ~i; i = edge[i].adj)
{
if(edge[i].to == fa)
continue;
dfs(edge[i].to, x, d + 1, flag);
}
}
int main()
{
int T; scanf("%d", &T);
while(T -- )
{
scanf("%d%d", &N, &Q);
init();
for(int i = 0; i < N - 1; i ++ )
{
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
dfs(1, 0, 0, 0);
dfs(info.nod1, 0, 0, 1);
while(Q -- )
{
scanf("%d", &k);
if(k <= info.dia)
printf("%d\n", k - 1);
else
printf("%d\n", info.dia + (k - (info.dia + 1)) * 2);
}
}
return 0;
}
Second, the diameter of the tree to solve the tree DP
Detailed tree DP
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e5 + 5;
int N, Q, k;
int head[maxN] ,cnt;
struct EDGE{
int adj, to;
EDGE(int a = 0, int b = 0): adj(a), to(b) {}
}edge[maxN << 1];
void add_edge(int u, int v)
{
edge[cnt] = EDGE(head[u], v);
head[u] = cnt ++ ;
}
int dia;
int first[maxN], second[maxN], upp[maxN];
int son_vis[maxN];
void dfs_down(int x, int fa)//向下遍历
{
first[x] = 0;
second[x]= 0;
for(int i = head[x]; ~i; i = edge[i].adj)
{
if(edge[i].to == fa)
continue;
dfs_down(edge[i].to, x);
if(first[x] < first[edge[i].to] + 1)
{
second[x] = first[x];
first[x] = first[edge[i].to] + 1;
son_vis[x] = edge[i].to;
}
else if(second[x] < first[edge[i].to] + 1)
second[x] = first[edge[i].to] + 1;
}
}
void dfs_up(int x, int fa)//向上遍历
{
for(int i = head[x]; ~i; i = edge[i].adj)
{
if(edge[i].to == fa)
continue;
if(son_vis[x] == edge[i].to)
upp[edge[i].to] = max(second[x], upp[x]) + 1;
else
upp[edge[i].to] = max(first[x], upp[x]) + 1;
dfs_up(edge[i].to, x);
}
dia = max(dia, upp[x] + first[x]);
}
void init()
{
memset(head, -1, sizeof(head));
cnt = 0;
dia = 0;
upp[1] = 0;
memset(son_vis, -1, sizeof(son_vis));
}
int main()
{
int T; scanf("%d", &T);
while(T -- )
{
scanf("%d%d", &N, &Q);
init();
for(int i = 0; i < N -1; i ++ )
{
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
dfs_down(1, 0);
dfs_up(1, 0);
for(int i = 0; i < Q; i ++ )
{
scanf("%d", &k);
if(k <= dia + 1)
printf("%d\n", k - 1);
else
printf("%d\n", dia + (k - (dia + 1)) * 2);
}
}
return 0;
}