洛谷 P3128 [USACO15DEC] Max Flow P 做題記錄

coding_goat_qwq發表於2024-10-23

因為一次新增會對點和邊都造成影響,而點一次能加兩個,於是最大值一定在點上。由於只有一次詢問,考慮樹上差分。
設一次詢問給出的兩點為 \(x,y\),那麼我們在 \(x\)\(y\) 處分別加 \(1\),在 \(\operatorname{lca}(x,y)\) 處減 \(1\),因為該點本身也有增加,於是我們在它的父節點再減去 \(1\) 即可。\(\operatorname{lca}\) 用倍增法求即可,時間複雜度 \(O(k\log n)\)

點選檢視程式碼
#include<bits/stdc++.h>

#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define inn(i,n,a) For(i,1,n) a[i]=read();

#define ll long long
#define i128 __int128

using namespace std;
inline int read() {
	int xx= 0;int f= 1;
	char c = getchar();
	while(c<'0'||c>'9') { 
		if(c=='-') f= -1;
		c= getchar();
	}
	while(c>='0'&&c<='9') {
		xx= (xx<<1)+(xx<<3)+(c^48);
		c= getchar();
	}
	return xx*f;
}
#define maxn 50050
int n,k;
vector<int>G[maxn];
int fa[maxn][26],dep[maxn];
int lg2(int x) {
	int res=0;
	if(x&0xffff0000) x>>=16,res+=16;
	if(x&0x0000ff00) x>>=8,res+=8;
	if(x&0x000000f0) x>>=4,res+=4;
	if(x&0x0000000c) x>>=2,res+=2;
	if(x&0x00000002) x>>=1,res+=1;
	return res;
}
void dfs(int u,int fath) {
	fa[u][0]=fath;
	dep[u]=dep[fath]+1;
	int sz=lg2(dep[u]);
	For(i,1,sz) fa[u][i]=fa[fa[u][i-1]][i-1];
	for(auto v:G[u]) if(v!=fath) dfs(v,u);
}
int lca(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	while(dep[x]>dep[y]) x=fa[x][lg2(dep[x]-dep[y])];
	if(x==y) return x;
	int k=lg2(dep[x]);
	Rep(i,k,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
int cnt[maxn],ans;
void dfs2(int u,int fa) {
	for(auto v:G[u]) if(v!=fa) {
		dfs2(v,u);
		cnt[u]+=cnt[v];
	}
	ans=max(ans,cnt[u]);
}
signed main() {
	in2(n,k);
	For(i,1,n-1) {
		int x,y;
		in2(x,y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs(1,0);
	For(i,1,k) {
		int x,y;
		in2(x,y);
		int l=lca(x,y);
		cnt[x]++,cnt[y]++;
		cnt[l]--,cnt[fa[l][0]]--;
	}
	dfs2(1,0);
	cout<<ans;
}