【USACO】 Max Flow

【题目链接】

           点击打开链接

【算法】

         LCA + 树上差分

【代码】

     

#include

using namespace std;

int i,x,y,N,K,l,maxn;
int anc[50010][50],d[50010],sum[50010];
vector E[50010];

void build(int x,int pre) {
		int i;
		for (i = 1; i <= 20; i++) anc[x][i] = anc[anc[x][i-1]][i-1];		
		for (i = 0; i < E[x].size(); i++) {
				if (E[x][i] != pre) {
						anc[E[x][i]][0] = x;
						d[E[x][i]] = d[x] + 1;
						build(E[x][i],x);
				}
		}
}

int lca(int x,int y) {
		int i,f;
		if (d[x] > d[y]) swap(x,y);
		f = d[y] - d[x];
		for (i = 0; i <= 20; i++) {
				if (f & (1 << i))
						y = anc[y][i];
		}	
		if (x == y) return x;
		for (i = 20; i >= 0; i--) {
				if (anc[x][i] != anc[y][i]) {
						x = anc[x][i];
						y = anc[y][i];
				}
		}
		return anc[x][0];
}

void query(int x,int pre) {
		int i;
		for (i = 0; i < E[x].size(); i++) {
				if (E[x][i] != pre) {
						query(E[x][i],x);
						sum[x] += sum[E[x][i]];
				}
		}	
		maxn = max(maxn,sum[x]);
}

int main() {
	
		cin >> N >> K;
		for (i = 1; i < N; i++) {
				cin >> x >> y;
				E[x].push_back(y);
				E[y].push_back(x);
		}
		
		build(1,0);
		
		for (i = 1; i <= K; i++) {
				cin >> x >> y;
				l = lca(x,y);
				sum[x]++; sum[y]++;
				sum[l]--;
				if (anc[l][0]) sum[anc[l][0]]--;		
		}
		
		query(1,0);
		
		cout<< maxn << endl;
		
		return 0;
}


你可能感兴趣的:(树上差分,最近公共祖先,倍增)