[Tree] in diameter tree DP_ HDU 4607 Park Visit

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

  1. When <When K = num, ans = K-1. (Away from the one end along a diameter of the diameter)

  2. 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 

  1. 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.

  2. 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;
}

 

 

Published 180 original articles · won praise 54 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_44049850/article/details/103898813