【p3128、LQB14I砍树】树上差分

2024-03-07 00:20

本文主要是介绍【p3128、LQB14I砍树】树上差分,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 差分
  • 树上差分
  • p3128
  • LQB14I砍树
    • 题目
    • 解题步骤
    • 代码样例

差分

差分数组求法:
设原始数组是arr,差分数组是b

  • b[0] = arr[0];
  • b[i] = arr[i] - arr[i-1];

在这里插入图片描述
如果我们要对图中2-4区间的数每个都加上3,就可以在差分数组2的位置加上3,在差分数组4的后一个元素即5的位置减去一个3(目的是消除3对后面区间的影响),再对差分数组前缀和即可完成。

树上差分

多次对树上路径做加法操作,然后询问对某个点操作后的值,适用树上差分。

差分数组求法:

  • 叶子节点的差分值是叶子节点的权重
  • 其他节点的差分值是权-子权和

在这里插入图片描述

  • 权 = 差分值 + 子权和

p3128

LQB14I砍树

题目

题目信息:
给定一棵由 n 个结点组成的树以及 m 个不重复的无序数对 (a1, b1), (a2, b2),
. . . , (am, bm),其中 ai 互不相同,bi 互不相同,ai ≠ bj(1 ≤ i, j ≤ m)。
小明想知道是否能够选择一条树上的边砍断,使得对于每个 (ai , bi) 满足 ai和 bi 不连通,如果可以则输出应该断掉的边的编号(编号按输入顺序从 1 开始),否则输出 -1.

输入输出:
输入共 n + m 行,第一行为两个正整数 n,m。
后面 n − 1 行,每行两个正整数 xi,yi 表示第 i 条边的两个端点。
后面 m 行,每行两个正整数 ai,bi。

一行一个整数,表示答案,如有多个答案,输出编号最大的一个。

输入:
6 2
1 2
2 3
4 3
2 5
6 5
3 6
4 5
4

输出:
4

解题步骤

  1. 要使砍掉一条边后每一数对都不连通,就要让所有数对都经过这条边。
  2. 将边权下移到点上,对x和y两点间的操作变为:s[x]++;s[y]++;s[LCA(x,y)]-=2;(其中s是差分数组)。
  3. 操作完成后,如果有边的权值恰好等于m,更新答案。

代码样例

#include <bits/stdc++.h>
using namespace std;const int N = 1e5+5;int n,m,dep[N],fa[N][21],ans,s[N];vector<int> e[N],num[N];void dfs(int u,int father){dep[u] = dep[father] + 1;fa[u][0] = father;for(int i = 1;i<=20;i++){fa[u][i] = fa[fa[u][i-1]][i-1];}for(int i = 0;i<e[u].size();i++){int v = e[u][i];if(v == father) continue;dfs(v,u);}
}int LCA(int u,int v)
{if(dep[u] < dep[v]) swap(u,v);for(int i = 20;i>=0;i--){if(dep[fa[u][i]] >= dep[v]) u = fa[u][i];}if(u == v) return u;for(int i = 20;i>=0;i--){if(fa[u][i] != fa[v][i]) u = fa[u][i] , v=fa[v][i];}return fa[u][0];
}void dfs2(int u,int Fa)
{for(int i = 0;i<e[u].size();i++){int v = e[u][i], p = num[u][i];if(v == Fa) continue;dfs2(v,u);s[u] += s[v];if(s[v] == m) ans=max(ans,p);}
//	if(s[u] == m) ans=max(ans,p);
} int main()
{cin >> n >> m;for(int i = 1;i<n;i++){int x,y;cin >> x >> y;e[x].push_back(y);e[y].push_back(x);num[x].push_back(i);num[y].push_back(i);}	dfs(1,0);	//差分for(int i = 1;i<=m;i++){int a,b;cin >> a >> b;s[a]++;s[b]++;s[LCA(a,b)]-=2;} //统计结果 dfs2(1,0);cout << ans << endl;return 0;
}

这篇关于【p3128、LQB14I砍树】树上差分的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/781844

相关文章

poj 3159 (spfa差分约束最短路) poj 1201

poj 3159: 题意: 每次给出b比a多不多于c个糖果,求n最多比1多多少个糖果。 解析: 差分约束。 这个博客讲差分约束讲的比较好: http://www.cnblogs.com/void/archive/2011/08/26/2153928.html 套个spfa。 代码: #include <iostream>#include <cstdio>#i

poj 3169 spfa 差分约束

题意: 给n只牛,这些牛有些关系。 ml个关系:fr 与 to 牛间的距离要小于等于 cost。 md个关系:fr 与 to 牛间的距离要大于等于 cost。 隐含关系: d[ i ] <= d[ i + 1 ] 解析: 用以上关系建图,求1-n间最短路即可。 新学了一种建图的方法。。。。。。 代码: #include <iostream>#include

POJ 1364差分约束

给出n个变量,m个约束公式 Sa + Sa+1 + .... + Sa+b < ki or > ki ,叫你判断是否存在着解满足这m组约束公式。 Sa + Sa+1   +   .+ Sa+b =  Sum[a+b] - Sum[a-1]  . 注意加入源点n+1 。 public class Main {public static void main(Strin

Python中差分进化differential_evolution的调用及参数说明

在场景应用中,要求我们的函数计算结果尽可能的逼近实际测量结果,可转化计算结果与测量结果的残差,通过最小化残差,便可求出最优的结果。但使用最小二乘等方法来计算时,常常会使迭代的结果显然局部最优点而导致结算错误。 差分进化原理 差分进化(Differential Evolution,DE)是一种基于群体差异的进化算法,其计算思想主要包括以下几个方面: 一、初始化种群 首先,随机生成一个初始种群

RS485差分信号不对称

在RS485总线通信中,差分信号不对称的问题时常出现,尤其是在总线未接从机设备的情况下。这一问题不仅影响通信质量,还可能导致信号传输错误。通过对实际波形、芯片手册及电路的深入分析,可以找出引发差分信号不对称的根本原因,并采取相应的解决措施。 问题描述 在RS485通信测试中,当总线上没有从机设备连接时,观察到RS485差分信号(A、B)关于地(GND)不对称。理想情况下,RS485的差分信

【POJ】3169 Layout 【HDU】3592 World Exhibition 差分约束

传送门:  【POJ】3169 Layout、【HDU】3592 World Exhibition 题目分析:我会说我只是凭直觉写的吗。。。。。。。 如果有B-A>=C形式的,则建边(B,A,-C)。 如果有B-A<=C形式的,则建边(A,B,C)。 对所有的点X,建边(X,X-1,0)。 最后跑一遍最短路。如果存在负环输出-1,如果点N不可达输出-2,否则输出点N的值(最短路径长

【codechef】 Prime Distance On Tree【求树上路经长度为i的路径条数】【点分治+FFT】

传送门:【codechef】 Prime Distance On Tree 点分治+FFT水题……竟然n*n爆int没发现…… 而且NTT TLE,FFT跑的超级快…… my  code: my~~code: #include <bits/stdc++.h>using namespace std ;typedef long long LL ;#define clr( a , x ) m

Xilinx FPGA 原语解析(二):IBUFDS差分输入缓冲器(示例源码及仿真)

目录 前言: 一、原语使用说明 二、原语实例化代码模版 三、使用示例 1.设计文件代码 2.仿真文件代码 3.仿真结果 前言: 本文主要参考资料xilinx手册,《Xilinx 7 Series FPGA and Zynq-7000 All Programmable SoC Libraries Guide for HDL Designs》UG768 (v14.7) Octob

差分、前缀和

P8218 【深进1.例1】求区间和  (前缀和) #include <bits/stdc++.h>using namespace std;int n, m, a[100010], sum[100010], ans, l, r;int main(){scanf("%d", &n);for(int i=1; i<=n; ++i){scanf("%d", &a[i]);sum[i]=sum[

差分约束题目

P5960 【模板】差分约束算法 #include <bits/stdc++.h>using namespace std;int n, m, v, u, w, dis[5001];bool flag;struct node{int from, to, weight;}edge[5001];int main(){cin >> n >> m;memset(dis, 0x3f, size