poj3471 - 倍增+LCA+树上差分

题意:一张n节点连通无向图,n-1条树边,m条非树边。若通过先删一条树边,再删一条非树边想操作

将此图划分为不连通的两部分,问有多少种方案。

利用LCA整好区间覆盖,dfs用来求前缀和

需要注意的是,覆盖数为1的时候才可以选择哦!

覆盖数为0,代表可以直接拆开

最后附上一张我老婆

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define maxn 110000
using namespace std;
typedef long long ll;
int dp[maxn][33];
int dep[maxn];
long long cnt[maxn];//差分数组
int head[450100];

struct Node {
	int to;
	int next;
}G[450100];
int cnn = 1;
void insert(int be, int en) {
	G[cnn].to = en; G[cnn].next = head[be]; head[be] = cnn;;//头插法
	cnn++;
}

void dfs(int u, int par) {
	dep[u] = dep[par] + 1;
	for (int i = 0; i <= 21; i++) {
		dp[u][i + 1] = dp[dp[u][i]][i];
	}
	for (int i = head[u]; i; i = G[i].next) {
		int p = G[i].to;
		if (p == par) continue;
		dp[p][0] = u;
		dfs(p, u);
	}
	return;
}
int LCA(int x, int y) {
	if (dep[x] < dep[y]) swap(x, y);//x在下面
	for (int i = 20; i >= 0; i--) {
		if (dep[dp[x][i]]  >= dep[y]) x = dp[x][i];
		if (x == y) return x;
	}

	for (int i = 20; i >= 0; i--) {
		if (dp[x][i] != dp[y][i]) {
			x = dp[x][i];
			y = dp[y][i];

		}
	}

	return dp[x][0];
}
int n, m;
int find(int x,int par) {

	for (int i = head[x]; i; i = G[i].next) {
		int p = G[i].to;
		if (p == par) continue;
		find(p, x);
		cnt[x] += cnt[p];
	}

	return 0;
}
int main() {
	scanf("%d %d", &n, &m);
	int be, en;
	for (int i = 0; i < n - 1; i++) {
		scanf("%d %d", &be, &en);
		insert(be, en);
		insert(en, be);
	}
	dp[1][0] = 1;
	dfs(1, 0);
	for(int i=0;i<m;i++) {
		scanf("%d %d", &be, &en);
		int p = LCA(be, en);
		cnt[p] -= 2;
		cnt[be]++;
		cnt[en]++;
	}
	find(1, 0);
	ll ans = 0;

	for (int i = 2; i <= n; i++) {
		if (cnt[i] == 0) ans += m;//乘法原理
		else if (cnt[i] == 1) ans++;
	}
	printf("%lld\n", ans);
	return 0;
}

原文地址:https://www.cnblogs.com/lesning/p/11448913.html

时间: 2024-10-10 02:38:13

poj3471 - 倍增+LCA+树上差分的相关文章

NOIp2015 运输计划 [LCA] [树上差分] [二分答案]

我太懒了 吃掉了题面 题解 & 吐槽 一道很好的树上差分练习题. 不加fread勉强a过bzoj和luogu的数据,加了fread才能在uoj里卡过去. 可以发现,答案则是运输计划里花费的最大值,最大值最小,便是二分答案的标志. 那么该怎么check呢... 我们得找出所有超过限制的计划,这个过程可以在LCA倍增的过程中预处理出来. 然后再找出一些被这些计划都覆盖的边,找到最大的那条边,如果最大的计划花费减去最大的那条边小于x,那么x就是可行的. 但是该怎么找到那些被计划都覆盖的边呢... 我们

POJ - 3417 Network (LCA+树上差分)

题目传送门:POJ - 3417 Network 题目大意: 存在一棵n个结点的树,加入m条新边,现在要让这个图不连通,你可以切断两条边,要求切断一条原边,一条新边,求切割的方案数. 分析: 加入m条新边,假设加入新边(u,v),那么u-->lca(u,v)-->v-->u形成一个环,此时可以切断新边,和环上任意的一条原边就可以使图不连通. 可以发现若加入一条新边,给环上的计数1,表示该边被一个环覆盖,树上有些边会被多个环覆盖,此时可以分情况讨论. 1.若该边被覆盖次数是0,则断掉该边后

【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家

[题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家.可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞.可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃. 维尼是个馋家伙,立马就

P2680 运输计划[二分+LCA+树上差分]

题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n?1 条双向航道,每条航道建立在两个星球之间,这 n-1n?1 条航道连通了 LL 国的所有星球. 小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 u_i*u**i* 号星球沿最快的宇航路径飞行到 v_i*v**i* 号星球去.显然,飞船驶过一条航道是需要时间的,对于航道 jj,任意飞船驶过它所花费的时间为 t_j*t**j*,并且任意两艘飞船之间不会产生任

习题:电压(LCA&amp;树上差分)

题目 思路 首先对于对于高低电压,其实就是二染色问题 有了这个想法之后 自然就会想到图中的环的奇偶性 如何快速的判断呢? 笔者用的是建树+LCA的办法 之后,如果是奇环,环上的所有的边+1 如果是偶环,则-1 用树上差分的办法可以以 \(O(1)\)的优秀时间复杂度处理 之后判断每一个边的值是否为奇环的总数即可 代码 #include<iostream> #include<vector> #include<cstring> #include<cstdio>

bzoj4390: [Usaco2015 dec]Max Flow(LCA+树上差分)

题目大意:给出一棵树,n(n<=5w)个节点,k(k<=10w)次修改,每次给定s和t,把s到t的路径上的点权+1,问k次操作后最大点权. 对于每次修改,给s和t的点权+1,给lca(s,t)和lca(s,t)的父亲的点权-1,每一个点的权就是它与它的子树权和,实际上就是树上的差分,又涨姿势了... 代码如下: uses math; type point=^rec; rec=record data:longint; next:point; end; var n,m,x,y,i,ans,fa,k

洛谷P3128 [USACO15DEC]最大流Max Flow [倍增LCA]

题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his barn (), conveniently numbered . Each pipe connects a pair of stalls, and all stalls are connected to each-other via paths of pipes. FJ is pumping milk

差分 and 树上差分

差分数组 定义 百度百科中的差分定义 //其实这完全和要讲的没关系 qwq 进去看了之后是不是觉得看不懂? 那我简单概括一下qwq 差分数组de定义:记录当前位置的数与上一位置的数的差值. 栗子 容易发现的是,\(\sum_{1}^{i}{b_i}\)即代表\(a_i\) 的值. \((\sum_{1}^{i}\) 即代表从1累加到i.) 思想 看到前面的\(\sum_{1}^{i}\) 你一定会发现这是前缀和! 那你认为这是前缀和? 的确是qwq. 实际上这并不是真正意义上的前缀和. 前缀和的

差分数组 and 树上差分

差分数组 定义 百度百科中的差分定义 //其实这完全和要讲的没关系 qwq 进去看了之后是不是觉得看不懂? 那我简单概括一下qwq 差分数组de定义:记录当前位置的数与上一位置的数的差值. 栗子 容易发现的是,\(\sum_{j=1}^{i} b_j\)即代表\(a_i\) 的值. \((\sum\) 即代表累加.) 思想 看到前面的\(\sum\) 你一定会发现这是前缀和! 那你认为这是前缀和? 的确是qwq. 实际上这并不是真正意义上的前缀和. 前缀和的思想是 根据元素与元素之间的并集关系(