大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

【十一联考 1】T2 树链剖分

算法思路就不说了,其实比较简单

这里讲一下坑点:

1.虽然我们可以将边权压到点上,但是当根不同时,差分数组显然不同。所以我们不能真的将边权看做点权,换根时还是要将其当做边权来考虑。
1.更新时,我们设dp[u]表示u节点为根时的最大价值,由于经过点u后,点v的儿子将变成点u,所以此时我们要更新点v的儿子中的最大值以及次大值。注意!不止要更新最大值,次大值也要正确维护

我的代码没有加优化,因为保证正确就不错了

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define head(x) for(int i=head[x];i+1;i=e[i].nxt)
#define int long long

const int inf=0x3f3f3f3f3f3f3f3f,N=1e5+10,t=17;

int n,m,head[N],cnt,son[N],c[N],dep[N],f[N][20],mx[N],se[N],ans=0,dp[N];

struct edge{
	int nxt,v;
}e[N*2];

void add(int u,int v){
	e[cnt]=(edge){head[u],v};
	head[u]=cnt++;
}

inline void read(int &x){
	x=0;char f=1,c=getchar();
	while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); }
	while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); }
	x*=f;
}

void dfs(int u,int fa){
	dep[u]=dep[fa]+1;
	f[u][0]=fa;
	head(u){
		int v=e[i].v;
		if(v==fa) continue;
		dfs(v,u);
	}
}

int lca(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	com(i,t,0){
		if(dep[f[x][i]]>=dep[y]) x=f[x][i];
	}
	if(x==y) return x;
	com(i,t,0){
		if(f[x][i]!=f[y][i])
			x=f[x][i],y=f[y][i];
	}
	return f[x][0];
}

void Dfs(int u,int fa){
	head(u){
		int v=e[i].v;
		if(v==fa) continue;
		Dfs(v,u);
		c[u]+=c[v];
	}
}

void DFS(int u,int fa){
	head(u){
		int v=e[i].v;
		if(v==fa) continue;
		DFS(v,u);
		if(c[v]>=mx[u]){
			se[u]=mx[u];
			mx[u]=c[v];
		}
		else if(c[v]>se[u]) se[u]=c[v];
	}
	dp[1]+=mx[u];
}

void DFs(int u,int fa){
	head(u){
		int v=e[i].v;
		if(v==fa) continue;
		dp[v]=dp[u];
		if(mx[u]==c[v]) dp[v]=dp[v]-mx[u]+se[u];
		if(c[v]>=mx[v]){
			dp[v]=dp[v]+c[v]-mx[v];
			se[v]=mx[v];
			mx[v]=c[v];
		}
		else if(c[v]>se[v]) se[v]=c[v];
		DFs(v,u);
	}
}

signed main(){
	mem(head,-1);
	read(n),read(m);
	int u,v,Lca;
	go(i,2,n){
		read(u),read(v);
		add(u,v),add(v,u);
	}
	dfs(1,0);
	go(j,1,t)
		go(i,1,n)
			f[i][j]=f[f[i][j-1]][j-1];
	while(m--){
		read(u),read(v);
		Lca=lca(u,v);
		++c[u],++c[v];
		c[Lca]-=2;
		ans+=dep[u]+dep[v]-2*dep[Lca];
	}
	Dfs(1,0);
	DFS(1,0);	
	DFs(1,0);
	int tot=ans;
	go(i,1,n)
		ans=min(ans,tot-dp[i]);
	printf("%lld",ans);
	return 0;
}
posted @ 2019-10-01 21:24  White_star  阅读(173)  评论(0编辑  收藏  举报
}