Wannafly挑战赛1 C-MMset2

题目链接:
在这里插入图片描述
解题报告:
最优点必然在点集S中最远两点的简单路径上且是中点。
个人解释:
假设u~v 为点集中拥有最远距离的简单路径,若最优点不在其上,那么 f(u)必然不是最小的,而题意是求min f(u);既然在该条简单路径上,那说明中点就是最优点

好多题解是建虚树,本人不会。
一些拓展知识
树的直径: 树上的最长简单路径。
解法:
原理:距某个点最远的叶子节点一定是树的某一条直径的端点。
那么可以任选一点求得一直径端点,再以该端点求最长路径。
待纠正!!

#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=3e5+5;
const int MOD=998244353;
const double PI=acos(-1);
const double e=2.718281828459;

int deep[maxn],f[maxn][25];
vector<int>edge[maxn];
int p[maxn];

void dfs(int now,int pre)
{
    deep[now]=deep[pre]+1;
    f[now][0]=pre;
    for(int i=1;i<=20;i++){
        f[now][i]=f[f[now][i-1]][i-1];
    }
    for(int i=0,j;i<edge[now].size();i++){
        j=edge[now][i];
        if(j==pre){continue;}
        dfs(j,now);
    }
}
int LCA(int x,int y)
{
    if(deep[x]<deep[y]){swap(x,y);}
    for(int i=20;i>=0;i--){
        if(deep[f[x][i]]>=deep[y]){x=f[x][i];}
    }
    if(x==y){return x;}
    for(int i=20;i>=0;i--){
        if(f[x][i]!=f[y][i]){
            x=f[x][i];
            y=f[y][i];
        }
    }
    return f[x][0];
}
int main()
{
    int n,s,u,v,q;
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        edge[u].pb(v);
        edge[v].pb(u);
    }
    deep[0]=0;
    dfs(1,0);
    scanf("%d",&q);
    while(q--){
        scanf("%d",&s);
        int root=0,mx=-1;
        for(int i=1;i<=s;i++){
            scanf("%d",&p[i]);
            if(deep[root]<deep[p[i]]){root=p[i];}
        }
        for(int i=1;i<=s;i++){
            if(root==p[i]){continue;}
            int pp=LCA(root,p[i]);
            mx=max(mx,deep[root]+deep[p[i]]-2*deep[pp]);
        }
        printf("%d\n",(mx+1)/2);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值