旅游规划【换根dp求可能存在于树的直径上的点】

题目链接


  题意:求N个点,序号从0~N-1的一棵树,求可能存在于树的直径上的点,并将他们的坐标升序输出。

  可以先利用树形dp的方式求得树的直径,然后根据换根dp的方法,我们可以求得以每个点作为中心时候的最远到达的距离是多长,来判断是否可以构成树的直径。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, head[maxN], cnt;
struct Eddge
{
    int nex, to;
    Eddge(int a=-1, int b=0):nex(a), to(b) {}
} edge[maxN << 1];
inline void addEddge(int u, int v)
{
    edge[cnt] = Eddge(head[u], v);
    head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
int dp[maxN][2], maxD;
void dfs(int u, int fa)
{
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == fa) continue;
        dfs(v, u);
        if(dp[u][0] < dp[v][0] + 1)
        {
            dp[u][1] = dp[u][0];
            dp[u][0] = dp[v][0] + 1;
        }
        else if(dp[u][1] < dp[v][0] + 1)
        {
            dp[u][1] = dp[v][0] + 1;
        }
        maxD = max(maxD, dp[u][0] + dp[u][1] + 1);
    }
}
vector ans;
void change_root(int u, int fa, int deep)
{
    if(max(deep, dp[u][1]) + dp[u][0] + 1 == maxD) ans.push_back(u);
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == fa) continue;
        change_root(v, u, (dp[v][0] + 1 == dp[u][0] ? max(dp[u][1], deep) + 1 : max(dp[u][0], deep) + 1) );
    }
}
inline void init()
{
    cnt = 0; maxD = 0;
    for(int i=0; i<=N; i++) head[i] = -1;
}
int main()
{
    scanf("%d", &N);
    init();
    for(int i=1, u, v; i

 

你可能感兴趣的:(DP动态规划)