首页 > 其他分享 >Codeforces Round 903 (Div. 3) F. Minimum Maximum Distance

Codeforces Round 903 (Div. 3) F. Minimum Maximum Distance

时间:2024-08-13 12:16:17浏览次数:6  
标签:903 Distance int Codeforces st mark d2 节点 d1

https://codeforces.com/contest/1881/problem/F

不难发现一件事情,我们这里最后的答案所在的点是 1 和 3 号点。

我们有没有发现一个性质:就是这两个点都是红点间的路径上的,而且最后的答案就是最长的红点间的距离的长度除以二上取整。

那么,我们怎么找到最长的红点间的距离呢?

很显然,O(n^2)枚举两个点然后求距离是会超时的。

这里有一个比较奇妙的算法,就是先钦定一个红点为根节点,然后不停地删除每一条边上的叶子节点,直到这个叶子节点为红点位置就停止在这一条树枝上的操作。
接着,我们删完点后,求出整棵树的直径,也就是红点间的最长距离。

具体为什么呢?

因为很显然,我们删完点后,所有的叶子结点都是红色节点,而直径本身就是从一个叶子节点到另外一个叶子节点,所以这个时候我们求出来的答案救赎对的。

最后我们只需要把直径的长度除以二后向上取整即可。

这里删除节点的复杂度是 O(n) 的,而求直径的dfs 也是 O(n) 的,所以最后的复杂度显然就是 O(n) 的。

#include<bits/stdc++.h>
//#define x first
//#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=4e5+10,M=2010;
int n,k,res;
int e[N],ne[N],h[N],idx;
bool mark[N],st[N];
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs1(int u,int father)//删点
{
    int cnt=0;
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j==father) continue;
        dfs1(j,u);
        if(!st[j]) cnt++;
    }
    if(!cnt&&!mark[u]) st[u]=true;
}
int dfs2(int u,int father)//求树的直径
{
    int d1=0,d2=0;
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j==father||st[j]) continue;
        int d=dfs2(j,u)+1;
        if(d>d1) d2=d1,d1=d;
        else if(d>d2) d2=d;
    }
    res=max(res,d1+d2);
    return d1;
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);

    int t;
    cin>>t;
    while(t--)
    {
        memset(h,-1,sizeof h);
        memset(mark,0,sizeof mark);
        memset(st,0,sizeof st);
        cin>>n>>k;
        int root;
        while(k--)
        {
            int x;
            cin>>x;
            mark[x]=true;
            root=x;
        }
        for(int i=0;i<n-1;i++)
        {
            int a,b;
            cin>>a>>b;
            add(a,b);
            add(b,a);
        }
        dfs1(root,-1);
        res=0;
        dfs2(root,-1);
        cout<<(res+1)/2<<endl;
    }

    return 0;
}

标签:903,Distance,int,Codeforces,st,mark,d2,节点,d1
From: https://www.cnblogs.com/djhjojo/p/18356617

相关文章

  • Codeforces Round 964 (Div. 4)
    CodeforcesRound964(Div.4)标题CodeForces1999A.A+BAgain?时限1second空限256megabytes题目描述给定一个两位数的正整数\(n\),求其数字之和。输入第一行包含一个整数\(t\)(\(1\leqt\leq90\))——测试用例的数量。每个测试用例的唯一一行包含一个两位数的正......
  • Codeforces Round 963 (Div. 2)
    Preface有懒狗上周日的比赛拖到这周日才写博客,我不说是谁这场比赛的时候因为C数组没开两倍卡了1h最后写对拍才看出来,直接心态爆炸导致D没写完掉大分A.QuestionMarks签到#include<cstdio>#include<iostream>#include<utility>#include<vector>#include<cstring>......
  • Codeforces Round 965 (Div. 2) 题解
    个人难度顺序:A<D<B<C<E。A.FindKDistinctPointswithFixedCenter如果\(k\)是偶数,构造\((x_c+i,yc+i)\),其中\(-\frac{k}{2}\lei\le\frac{k}{2}\)。对于\(k\)是奇数,先加一个点\((xc,yc)\),然后就变成偶数的情况了。B.MinimizeEqualSumSubarr......
  • Codeforces Round 965 (Div. 2) 补题记录(A,B,D,E1)
    speedforcesagain~A<E1<<B<D<<CA若\(k\equiv1(\bmod2)\),则构造\((x,y)\),\((x-1,y)\),\((x+1,y)\),\((x-2,y)\),\((x+2,y)\),\(\ldots\)。否则构造\((x-1,y)\),\((x+1,y)\),\((x-2,y)\),\((x+2,y)\),\(\ldots\)。#pra......
  • ABC201E Xor Distances 题解
    ABC201EXorDistances题解题目大意给定一个带权树,求树上每两点的简单路径上的边权的异或和的和。形式化的,定义\(dis(i,j)\)为\(i\)到\(j\)的简单路径上的边权的异或和,求\(\large\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n\text{dis}(i,j)\)。Solve令\(\largef(u)=......
  • Codeforces Round 964 (Div. 4)
    这场的题不错,就是一直在inqueue......
  • Codeforces 165E Compatible Numbers 题解
    思路高维前缀和高维前缀和把数的二进制看成一个集合,二进制的每一位为\(1\)为全集\(V\)。根据题目描述,若两数\(a,b\)相容,则\(a\operatorname{and}b=0\),容易发现,\(b\in\complement_{V}a\),所以我们只需要用高维前缀和处理出\(\complement_{V}a\)的一个元素即可。......
  • 论文笔记:Investigation of Passengers’ Perceived Transfer Distance in Urban Rail
    (基于XGBoost和SHAP的城市轨道交通站点乘客感知换乘距离研究)话题点:城市轨道交通站点、换乘距离、XGBoost模型、SHAP模型:感知传输距离偏差theRatioofPerceivedTransferDistanceDeviation(R)、XGBoost和SHAP模型考虑的因素:乘客个人属性、换乘设施和换乘环境相关的32个指......
  • Codeforces Round 964 (Div. 4)
    知识点1.对于两个数字,一个乘n,一个除以n,可以理解为n进制下的这个数乘10和除10。比如E题用这个知识点就可以很快的解决问题。题解A.A+BAgain?#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;voidsolve(){ strings; cin>>s; cout<<s[0]-'0'+s[1]-......
  • Codeforces Round 964 (Div. 4)
    CodeforcesRound964(Div.4)A送分B大意:两个人两张牌随机翻求a翻出来的牌比b大的可能#include<cstdio>#include<cmath>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#defineepemplace_backusingnamespace......