首页 > 其他分享 >P4183 [USACO18JAN] Cow at Large P 题解

P4183 [USACO18JAN] Cow at Large P 题解

时间:2023-08-17 15:01:39浏览次数:50  
标签:70010 USACO18JAN int 题解 void Large hea front make

题意分析

我们首先想到,枚举贝茜在 \(x\) 点,枚举度数大于 \(2\) 的点为 \(y\)。设 \(x\) 的度数为 \(a\),\(y\) 的度数为 \(b\)。

我们首先发现每个 \(x\) 点都有一个初始的贡献为 \(a\) 条通往叶子的路径。

如果点 \(y\) 到最近的叶子节点的距离大于到 \(x\) 的点的距离(农夫不能在 \(y\) 点追上贝茜),则 \(y\) 点可以贡献额外的 \(b-2\) 条路径。(\(y\) 的度数减去进入 \(y\)、离开 \(y\) 的初始贡献消耗的度数)。

我们考虑先预处理出每个 \(y\) 点到最近的叶子节点的距离为 \(mi_y\)。

void bfs(int x){
    queue<pair<int,int> >q;
    q.push(make_pair(x,0));
    bool v[70010]={};
    while(!q.empty()){
        int y=q.front().first,z=q.front().second;
        q.pop();
        for(int i=hea[y];i;i=nex[i]){
            int t=to[i];
            if(v[t]!=1){
                v[t]=1;
                if(siz[t]==1){
                    mi[x]=z+1;
                    return;
                }
                q.push(make_pair(t,z+1));
            }
        }
    }
}

然后再从 \(x\) 点搜索出所有的 \(y\) 点计算出合法贡献。注意不能加上自己。

void dfs(int x,int nu,int fa){
    if(siz[x]>2){
        if(nu<mi[x]&&nu!=0) ans+=siz[x]-2;
        tot++;
    }
    if(tot>=num) return ; 
    for(int i=hea[x];i;i=nex[i]){
        int t=to[i];
        if(t!=fa){
            dfs(t,nu+1,x);
        }
    }
}

我们发现这样会 TLE \(5\) 个点。

我们考虑优化,我们发现枚举的 \(x\) 点数量太多。我们可以枚举 \(y\) 点反推 \(x\) 点。

像这样:

void bf(int x){
    queue<pair<int,int> >q;
    q.push(make_pair(x,0));
    bool v[70010]={};
    while(!q.empty()){
        int y=q.front().first,z=q.front().second;
        q.pop();
        if(y!=x)
        an[y]+=siz[x]-2;
        if(z+1<mi[x])
        for(int i=hea[y];i;i=nex[i]){
            int t=to[i];
            if(v[t]!=1){
                v[t]=1;
                q.push(make_pair(t,z+1));
            }
        }
    }
}

证明一下复杂度:

我们考虑最坏复杂度,此时树为一棵满二叉树。

img

我们设树总共有 \(m\) 层。

第 \(1\) 层不会遍历。

第 \(2\) 层有 \(2^{2-1}\) 个数,每个数会遍历 \(2^{m-1}-1+1\) 次。

有什么规律呢?

我们把向上的部分转移位置,例如 \(2\) 号节点是这样的:

img

如果有更多节点,图就变成了这样。

img

对于第 \(i\) 层遍历了 \(2^{i-1}\times(2^{m-i}-1+2^{m-i-1})\) 次。

化简一下并去掉常数就是 \(2^{m-1}\times2^{m-2}=3\times{2^{m-2}}\) 次。

由于是一个满二叉树,节点数 \(n=2^m-1\),\(m\approx{log(n)}\)。

所以复杂度就是 \(m\times{\tfrac{3}{4}\times{2^m}}\approx{O(n\log{n})}\)。

由于常数较小,故比点分治快。

code

#include<iostream>
#include<queue>
#include<cstdio>
#include<utility>
using namespace std;
int n,siz[70010],mi[70010],num,ans,ma;
int tot,hea[70010],nex[200010],to[200010],an[70010];
void add(int x,int y){
    to[++tot]=y;
    nex[tot]=hea[x];
    hea[x]=tot;
}
void bfs(int x){
    queue<pair<int,int> >q;
    q.push(make_pair(x,0));
    bool v[70010]={};
    while(!q.empty()){
        int y=q.front().first,z=q.front().second;
        q.pop();
        for(int i=hea[y];i;i=nex[i]){
            int t=to[i];
            if(v[t]!=1){
                v[t]=1;
                if(siz[t]==1){
                    mi[x]=z+1;
                    return;
                }
                q.push(make_pair(t,z+1));
            }
        }
    }
}
void bf(int x){
    queue<pair<int,int> >q;
    q.push(make_pair(x,0));
    bool v[70010]={};
    while(!q.empty()){
        int y=q.front().first,z=q.front().second;
        q.pop();
        if(y!=x)
        an[y]+=siz[x]-2;
        if(z+1<mi[x])
        for(int i=hea[y];i;i=nex[i]){
            int t=to[i];
            if(v[t]!=1){
                v[t]=1;
                q.push(make_pair(t,z+1));
            }
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
        siz[x]++;
        siz[y]++;
    }
    for(int i=1;i<=n;i++){
        if(siz[i]>2){
            bfs(i);
            num++;
            ma=max(ma,mi[i]);
        }
    }
    for(int i=1;i<=n;i++){
        if(siz[i]>2){
            bf(i);
        }
    }
    for(int i=1;i<=n;i++){
        if(siz[i]==1){
            printf("1\n");
        }
        else{
            ans=siz[i];
            tot=0;
            printf("%d\n",ans+an[i]);
        }
    }
    return 0;
}

标签:70010,USACO18JAN,int,题解,void,Large,hea,front,make
From: https://www.cnblogs.com/muzqingt/p/17636210.html

相关文章

  • 安防监控视频汇聚平台EasyCVR视频平台调用iframe地址无法播放的问题解决方案
    安防监控视频汇聚平台EasyCVR基于云边端一体化架构,具有强大的数据接入、处理及分发能力,可提供视频监控直播、云端录像、视频云存储、视频集中存储、视频存储磁盘阵列、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、AI算法中台智能分析无缝对接等功能。为了便于用户......
  • 安防监控视频汇聚平台EasyCVR视频平台调用iframe地址无法播放的问题解决方案
    安防监控视频汇聚平台EasyCVR基于云边端一体化架构,具有强大的数据接入、处理及分发能力,可提供视频监控直播、云端录像、视频云存储、视频集中存储、视频存储磁盘阵列、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、AI算法中台智能分析无缝对接等功能。为了便于用户二......
  • vue项目在360浏览器兼容模式下SCRIPT1002: 语法错误以及“fetch”未定义问题解决
    使用360浏览器的兼容模式,vue项目页面空白,打开控制台,发现如下报错:SCRIPT1002:语法错误 解决方法如下:1、安装依赖npminstall--savecore-jsregenerator-runtime2、在main.js引入import'core-js/stable';import'regenerator-runtime/runtime';3、在babel.confi......
  • CF1545B题解
    CF1545B题解题目描述你有一个长为\(n\)的棋盘,这个棋盘上有一些棋子,你可以进行如下操作:如果第\(i+2\)个位置是空的,且第\(i+1\)个位置非空,则可以将第\(i\)个位置的棋子挪到第\(i+2\)个位置(\(i+2\leqn\)).如果第\(i-2\)个位置是空的,且第\(i-1......
  • arc136,arc137,arc138题解
    ARC136A-EAA↔BB贪心。可以把BB换成A,可以把BA换成AB。BTripleShift直观上觉得只要数集相同,那么就是可以变换的。大概方法就是每次找到正确的数把它挪到数列的端点,这样显然是可行的。但是在相反的三个上出现了问题,原因在于只剩最后两个数时方向可能是反着的。分析......
  • arc133,arc134,arc135题解
    ARC133A-EAErasebyValue扣掉一个数当且仅当这个数后面有更小的数。特判单增即可。BDividingSubsequence相对比较有启发性。发现有倍数关系的数对只有\(O(n\logn)\)对,于是可以把对应下标攒成一堆二元组,于是一个合法的取数方案就变成了两个维度分别严格上升的元素集合......
  • arc130,arc131,arc132题解
    ARC130A-DARemoveOneCharacter对每个连续块分别处理即可。BColorfulLines非常经典的题目,对于每一行每一列记录最后出现的颜色并计算贡献即可。CDigitSumMinimization有点细节。枚举最后两个数,显然加起来超过十是很好的;然后前面的数应该尽量凑九,然后要注意尽量不选......
  • FJOI2018 领导集团问题 题解
    先考虑暴力dp。设\(f_{u,x}\)表示在子树\(u\)中选出的节点集合的\(w\)最小值为\(x\)的情况下,最大的节点集合的大小。有两种转移(选不选\(u\)):\(f_{u,x}\gets\sum\limits_{v\in\text{substree}_u}f_{v,\gex}\)\(f_{u,w_u}\gets\sum\limits_{v\in\text{substree}_u}......
  • [CF1730D] Prefixes and Suffixes 题解
    首先发现后缀和前缀比较不好看,所以翻转第二个字符串,记为\(T'\)。这样就变成了操作两个字符串的前缀。观察发现,操作\(k\)等价于交换\(S[1\simk]\)和\(T'[1\simk]\),然后翻转\(S[1\simk]\)和\(T'[1\simk]\)。结论1:同一个下标上的字符对恒定。因为我们所有的操作都......
  • CF932E Team Work 题解
    Description给定\(n,k\),求:\[\displaystyle\sum_{i=1}^{n}{\binom{n}{i}\timesi^k}\]\(1\leqk\leq5000,1\leqn\leq10^9\)。Solution看到那个\(i^k\)很不爽,但是\(k\)很小,考虑用斯特林数改写一下:\[i^k=\sum_{j=0}^{k}{\binom{i}{j}\left\{{\begin{matrix}k......