差分总结三 练习题 闇の連鎖+2015沈阳网络赛 HDU 5452 Minimum Cut

下面2题 差不多 都是边差分

闇の連鎖

https://www.acwing.com/problem/content/354/
这个题 删一个树边 和 一个非树边 让树不连通
那样 删一个 经过边是 0 的树边 和 删 一个 经过边是 1 的树边 才能成功
前置 是 m0 * m 数量 后者 是唯一确定的

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

int n, m;
int head[maxn], cnt;
int nxt[maxn << 1], to[maxn << 1];

void ade(int a, int b) {
	to[++ cnt] = b;
	nxt[cnt] = head[a], head[a] = cnt;
}

int depth[maxn], fa[maxn][25];
void dfs_lca(int x, int pre) {
	depth[x] = depth[pre] + 1;
	fa[x][0] = pre;
	for(int i = 1; (1 << i) <= depth[x]; i ++)
		fa[x][i] = fa[fa[x][i - 1]][i - 1];
	for(int i = head[x]; i; i = nxt[i])
		if(to[i] != pre) {
			dfs_lca(to[i], x);
		}
}

int LCA(int x, int y) {
	if(depth[x] > depth[y]) swap(x, y);
	for(int i = 24; ~i; -- i)
		if(depth[x] <= depth[y] - (1 << i))
			y = fa[y][i];
	if(x == y) return x;
	for(int i = 24; ~i; -- i)
		if(fa[x][i] != fa[y][i])
			x = fa[x][i], y =fa[y][i];
	return fa[x][0];
}

int coun[maxn];
void dfs(int x, int pre) {
	for(int i = head[x]; i; i = nxt[i]) {
		int y = to[i];
		if(y == pre) continue;
		dfs(y, x);
		coun[x] += coun[y];
	}
}

signed main() {
	scanf("%d %d", &n, &m);
	for(int i = 1, a, b; i < n; i ++) {
		scanf("%d %d", &a, &b);
		ade(a, b), ade(b, a);
	}
	dfs_lca(1, 0);
	for(int i = 1, a, b; i <= m; i ++) {
		scanf("%d %d", &a, &b);
		int lca = LCA(a, b);
		++ coun[a], ++ coun[b], coun[lca] -= 2;
	} 
	dfs(1, 0);
	int m1 = 0, m2 = 0;
	for(int i = 2; i <= n; i ++) {
		if(coun[i] == 0) m1 ++;
		else if(coun[i] == 1) m2 ++;
	}
	printf("%d\n", m1 * m + m2);
	return 0;
}

2015沈阳网络赛 HDU 5452 Minimum Cut

必须删一个树边 和 删其他 非树边 最少 删几个 不连通
只要有一个 树边 没有被覆盖过 删他就完成了 次数是1
如果没有 找 最小被覆盖的 + 1 所有路过这树边的边 + 这个树边

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

int n, m, cas;
int head[maxn], cnt;
int nxt[maxn << 1], to[maxn << 1];

void ade(int a, int b) {
	to[++ cnt] = b;
	nxt[cnt] = head[a], head[a] = cnt;
}

int depth[maxn], fa[maxn][25];
void dfs_lca(int x, int pre) {
	depth[x] = depth[pre] + 1;
	fa[x][0] = pre;
	for(int i = 1; (1 << i) <= depth[x]; i ++)
		fa[x][i] = fa[fa[x][i - 1]][i - 1];
	for(int i = head[x]; i; i = nxt[i])
		if(to[i] != pre) {
			dfs_lca(to[i], x);
		}
}

int LCA(int x, int y) {
	if(depth[x] > depth[y]) swap(x, y);
	for(int i = 24; ~i; -- i)
		if(depth[x] <= depth[y] - (1 << i))
			y = fa[y][i];
	if(x == y) return x;
	for(int i = 24; ~i; -- i)
		if(fa[x][i] != fa[y][i])
			x = fa[x][i], y =fa[y][i];
	return fa[x][0];
}

int coun[maxn];
void dfs(int x, int pre) {
	for(int i = head[x]; i; i = nxt[i]) {
		int y = to[i];
		if(y == pre) continue;
		dfs(y, x);
		coun[x] += coun[y];
	}
}

signed main() {
	scanf("%d", &cas);
	for(int CAS = 1; CAS <= cas; CAS ++) {
		scanf("%d %d", &n, &m);
        memset(head, 0, (n + 5) * sizeof (int));
        cnt = 0;
		for(int i = 1, a, b; i < n; i ++) {
			scanf("%d %d", &a, &b);
			ade(a, b), ade(b, a);
		}
		dfs_lca(1, 0);
        memset(coun, 0, (n + 5) * sizeof(int));
		for(int i = 1, a, b; i <= m - n + 1; i ++) {
			scanf("%d %d", &a, &b);
			int lca = LCA(a, b);
			++ coun[a], ++ coun[b], coun[lca] -= 2;
		}
		dfs(1, 0);
		int ans = 0x3f3f3f3f;
		for(int i = 2; i <= n; i ++) {
			if(coun[i] == 0) ans = 1;
			else if(coun[i]) ans = min(ans, coun[i] + 1);
		}
		printf("Case #%d: ", CAS);
		printf("%d\n", ans);
	}
	return 0;
}
全部评论

相关推荐

09-09 09:17
已编辑
东华理工大学 Java
点赞 评论 收藏
分享
码农索隆:谁问你了 举报了 删了,求你了 我要哭了 我一点也不眼红 我要跳楼
点赞 评论 收藏
分享
2025年10月3日中午,在写完定时一年后发给自己的信之后,敲下键盘,写下这篇文字。我把标题的“所有人”加了引号,因为如我们所见,确实有的人顺风顺水,每天过的很开心,或是早早进入大厂,或是年纪轻轻就拿到了高薪offer,或是过着可能我努力十年也不一定实现的生活。但也许,不是每个人的痛苦都能被别人看到的,这个月我经常会哭,被骗6000块钱、手上钱不够导致拖欠房租、生活还要借朋友钱、国庆长假也没有钱去旅游,互联网公司不稳定担心试用期不过(毕竟上段实习就是被裁了,一有点风吹草动就害怕),但这样的我,不是所有人都知道的,居然是有些朋友的羡慕对象。回忆我的七年“长跑”别人都是多年幸福的恋爱长跑,我没有恋...
故事和酒66:让每一颗种子找到合适自己的生长方式,最终绽放出独一无二的花朵,这远比所有人都被迫长成同一棵“参天大树”的世界,更加美好和富有生机。这是社会和环境的问题,而不是我们的问题。然而就是在这样的环境中,楼主依然能突破自我,逆势成长,其中的艰辛可想而知。这一路的苦难终究会化作你成长的养料
你小时候最想从事什么职业
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务