【51Nod1405】树上距离和 二次扫描与换根法

题目大意:给定一棵 N 个点的边权均为 1 的树,依次输出每个点到其他各个点的距离和。

题解:首先任意选定一个节点为根节点,比如 1,第一遍 dfs 遍历树求出子树大小、树上前缀和。第二遍 dfs 遍历这棵树,求出各个点的距离和。

对于遍历到的任意一个节点 i,对于与之相邻的节点 j 来说,答案贡献由 i 到 j 转移首先减小了 \(size[j]*1\),同时增加了 \((n-size[j])*1\),因此可以直接得到\(dp[j]=dp[i]+n-size[j]*2\)。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;

inline int read(){
    int x=0,f=1;char ch;
    do{ch=getchar();if(ch==‘-‘)f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-‘0‘;ch=getchar();}while(isdigit(ch));
    return f*x;
}

struct node{
    int nxt,to;
}e[maxn<<1];
int tot=1,head[maxn];
int n,size[maxn],sum[maxn],dp[maxn];

inline void add_edge(int from,int to){
    e[++tot]=node{head[from],to},head[from]=tot;
}

void read_and_parse(){
    n=read();
    for(int i=1;i<n;i++){
        int from=read(),to=read();
        add_edge(from,to),add_edge(to,from);
    }
}

void dfs1(int u,int fa){
    size[u]=1;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;if(v==fa)continue;
        sum[v]=sum[u]+1;
        dfs1(v,u);
        size[u]+=size[v];
    }
    dp[1]+=sum[u];
}

void dfs2(int u,int fa){
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;if(v==fa)continue;
        dp[v]=dp[u]+n-(size[v]<<1);
        dfs2(v,u);
    }
}

void solve(){
    dfs1(1,0),dfs2(1,0);
    for(int i=1;i<=n;i++)printf("%d\n",dp[i]);
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10013693.html

时间: 2024-10-11 00:39:58

【51Nod1405】树上距离和 二次扫描与换根法的相关文章

题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)

写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换根法 作为一道不定根的树形DP,如果直接对每个点进行DP,可能时间会炸掉 但是,优秀的二次换根和扫描法可以再O(n^2)内解决问题. 二次扫描的含义:(来自lyd 算法竞赛进阶指南) 第一次扫描:任选一个节点为根节点(我会选1)在树上进行树形DP,在回溯时,从儿子节点向父节点(从底向上)进行状态转移

HDU 2196 Computer 二次扫描与换根DP

题意:给定一棵树,求树上所有点到其最远点的距离. 数据范围: 1 <= N <= 100000 ------------------------------------------我是分割线------------------------------------------ 题解:对于每个节点u来说,其可能到达的最长距离为max{其子树内的最长距离,其父节点不经过u的子树内的最长距离}.于是,我们便可以在第一遍dfs中预处理节点x到其子树内的最长距离,顺带求一下次长距离,方便转移. // f[

电子词典--两次扫描文件发/链表法

二次扫描文件法实现的电子词典 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> struct dict { char *key; char *content; }; int get_dict_size(FILE *pfile)//得到字典文件中词条总数 { if (pfile == NULL)

[问题2014A01] 解答二(后 n-1 列拆分法,由郭昱君同学提供)

[问题2014A01] 解答二(后 n-1 列拆分法,由郭昱君同学提供) \[|A|=\begin{vmatrix} 1 & x_1^2-ax_1 & x_1^3-ax_1^2 & \cdots & x_1^n-ax_1^{n-1} \\ 1 & x_2^2-ax_2 & x_2^3-ax_2^2 & \cdots & x_2^n-ax_2^{n-1} \\ \vdots & \vdots & \vdots & \vd

WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置:通过ChannelFactory<TChannel>创建服务代理对象.在这篇文章中,我们采用一种独特的方式进行服务的调用.从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用.在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服

信息安全技术实验二 网络扫描实验+ARP攻击

一.实验目的及要求 1. 了解扫描技术的工作原理: 2. 加深对网络底层的理解: 3. 掌握常用扫描工具的基本用法: 4. 学习扫描器程序设计的基本方法.(以后再补充) 二.实验环境及相关情况(包含使用软件.实验设备.主要仪器及材料等) 1.实验设备:微型计算机: 2.软件系统:Windows 7操作系统,Nmap. 三.实验内容 1. Windows平台下Nmap的安装. 2. Windows平台下Nmap的使用. 3. Windows平台下查看本地端口. 4. 端口扫描的防范. 四.实验步骤

《渗透测试实践指南:必知必会的工具与方法》-读书笔记(二)扫描

目标:建立IP地址与开放端口和服务的映射关系   扫描过程分解为三个不同的阶段: 1.验证系统是否正在运行 2.扫描系统的端口 3.扫描系统中的漏洞   漏洞扫描是一个定位.识别运行在目标计算机上的服务和软件有哪些已知漏洞的过程.   不管是想控制某些机密的内部机器还是仅仅想试图进入到一个目标网络中,一般都需要从扫描外部设备开始.原因: 1.侦查获取的大部分信息都是属于外部设备的 2.很难直接进入到目标网络中,所以逐跳控制   不是每一个主机都会响应ping请求,有些主机上的防火墙或其它设施会抑

51nod2621 树上距离一题四解ST表+倍增+Tarjan+树剖

LCA裸题 只有代码无原理,给自己复习用 1. ST表(这题2^10就够了) 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=2e3+50; 5 6 int cnt,dfn[maxn],dep[maxn],dp[maxn][21],lg2[maxn],dis[maxn],w[maxn][maxn]; 7 std::vector<int> G[maxn]; 8 void dfs(int u,in

操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)

实验二 进程调度 一.     实验目的 1.       理解进程运行的并发性. 2.       理解处理器的三级调度. 3.       掌握先来先服务的进程调度算法. 4.       掌握短进程优先的进程调度算法. 5.       掌握时间片轮转的进程调度算法. 二.     实验设备 1.     安装windows或者linux操作系统的PC机 2.     C程序编译环境 三.     实验内容 用c语言编程模拟实现至少一个操作系统的常见进程调度算法.常见的进程调度算法有先来先