poj3471 - + LCA + tree differential multiplier

The meaning of problems: a communication undirected graph nodes n, n-1 bar side of the tree, m article non-tree edges. If the edge by first cut a tree, and then delete a non-tree edge to operate   

This map is divided into two parts disconnected, asked how many kinds of programs.

 

 

 

 Covering the whole good section using LCA, dfs prefix for seeking and

It should be noted that the number of cover before they can choose when to Oh 1!

Covering number is 0, which means you can directly open

 

Finally, attach one of my wife

 

 

 

 

#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;
}

 

Guess you like

Origin www.cnblogs.com/lesning/p/11448913.html