Miraclys

一言(ヒトコト)

CF191C Fools and Roads

\(\Large\textbf{Description:} \large{有一颗 n 个节点的树,k 次旅行,问每一条边被走过的次数。}\)

\(\Large\textbf{Solution:} \large{树上差分板子??}\)

\(\Large\textbf{Code:}\)

#include <cstdio>
#include <algorithm>
#define LL long long
#define gc() getchar()
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int N = 1e5 + 5; 
int n, k, cnt, head[N], u[N], v[N], ans[N];
int size[N], top[N], dep[N], fa[N], son[N], w[N];

struct Edge {
	int to, next;	
}e[N << 1];

inline int read() {
	char ch = gc();
	int ans = 0, flag = 1;
	while (ch > '9' || ch < '0') {
		if (ch == '-') flag = -1;
		ch = gc();
	}	
	while (ch >= '0' && ch <= '9') ans = (ans << 1) + (ans << 3) + ch - '0', ch = gc();
	return ans;
}

inline void add(int x, int y) {
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}

inline void dfs1(int x, int y) {
	int Max = -1;
	dep[x] = dep[y] + 1;
	fa[x] = y;
	size[x] = 1;
	for (int i = head[x]; i ; i = e[i].next) {
		int U = e[i].to;
		if (U == y) continue;
		dfs1(U, x);
		size[x] += size[U];
		if (size[U] > Max) Max = size[U], son[x] = U;
	}	
}

inline void dfs2(int x, int y) {
	top[x] = y;
	if (!son[x]) return ;
	dfs2(son[x], y);
	for (int i = head[x]; i ; i = e[i].next) {
		int U = e[i].to;
		if (U == fa[x] || U == son[x]) continue;
		dfs2(U, U);
	}
}

inline int lca(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	}	
	if (dep[x] > dep[y]) swap(x, y);
	return x;
}

inline int dfs(int x) {
	int cur = w[x];
	for (int i = head[x]; i ; i = e[i].next) {
		int U = e[i].to;
		if (U == fa[x]) continue;
		cur += dfs(U);
	}
	return ans[x] = cur;
}

int main() {
	n = read();
	rep(i, 1, n - 1) { u[i] = read(); v[i] = read(); add(u[i], v[i]); add(v[i], u[i]); }
	dfs1(1, 0);//树剖 方便求lca。
	dfs2(1, 1);
	k = read();
	int l, r;
	rep(i, 1, k) l = read(), r = read(), ++w[l], ++w[r], w[lca(l, r)] -= 2;//边的差分。
	dfs(1);//最后遍历一遍树,每条边的走过次数就是它的子树和。
	rep(i, 1, n - 1) { if (dep[u[i]] > dep[v[i]]) swap(u[i], v[i]); printf("%d ", ans[v[i]]); }//差分时我们以每条边深度更深的那个点存储这条边的值。
	return 0; 
}

\(\large\color{pink}{by\quad Miraclys}\)

posted @ 2020-02-06 21:47  Miraclys  阅读(106)  评论(0编辑  收藏  举报

关于本博客样式

部分创意和图片借鉴了

BNDong

的博客,在此感谢