为什么这个 lca 会错啊?
查看原帖
为什么这个 lca 会错啊?
289056
北射天狼楼主2023/10/5 23:50
#include <bits/stdc++.h>//喵内~
#define re register//喵内~
#define int long long
using namespace std;//喵内~
typedef long long ll;
typedef long double ld;
const int N = 1e5 + 5;//喵内~要填数字哟~
const int INF = 1145141919810114514;
inline int read(){
    int s = 0,f = 1;char c = getchar();
    while (!isdigit(c)){if (c == '-')f = -1;c = getchar();}
    while (isdigit(c)){s = (s<<3) + (s<<1) + (c ^ 48);c = getchar();}
    return s * f;
}//喵内~
set<pair<int,int> > st;
int head[N],cnt;
struct node{
	int v,next;
}tree[N << 1];
int f[N][2],g[N][2],fh[N][20][2][2],val[N];
int dep[N],fa[N][20];
int n,m;
string s;
void add(int u,int v){
	tree[++cnt].next = head[u];
	tree[cnt].v = v;
	head[u] = cnt;
}
void dfs(int u,int father){
	dep[u] = dep[father] + 1;
	f[u][1] = val[u];
	fa[u][0] = father;
	for (int i=head[u];i;i=tree[i].next){
		int v = tree[i].v;if (v == father)continue;
		dfs(v,u);
		f[u][0] += f[v][1],f[u][1] += min(f[v][0],f[v][1]);
	}
}
void dfs2(int u,int father){
	for (int i=head[u];i;i=tree[i].next){
		int v = tree[i].v;
		if (v == father)continue;
		g[v][0] = g[u][1] + f[u][1] - min(f[v][0],f[v][1]);
		g[v][1] = min(g[u][0] + f[u][0] - f[v][1],g[v][0]);
		//g[v][1] = min{g[x][0] + f[x][0] - f[v][1],g[u][1] + f[u][1] - min(f[v][0],f[v][1])};
		dfs2(v,u);
		
	}
}
int solve(int x,int a,int y,int b){
	if (dep[x] < dep[y]){
	    swap(x,y),swap(a,b);
	}
	int tx[2] = {INF,INF},ty[2] = {INF,INF};
	int nx[2],ny[2];
	tx[a] = f[x][a],ty[b] = f[y][b];
	//tx,ty 分别表示在 x,y 子树下取 z 的最xiao值,这个值跟初始  x,y 无关。 
	//nx,ny 用于更新最大值,作用不大。 
	for (int j=20;j >= 0;j--){
		if (dep[fa[x][j]] >= dep[y]){
			nx[0] = nx[1] = INF;
			for (int u=0;u<2;u++)
			    for (int v=0;v<2;v++){
			    	nx[v] = min(nx[v],tx[u] + fh[x][j][u][v]);
				}
			tx[1] = nx[1],tx[0] = nx[0],x = fa[x][j];
		}
	}
	cout << tx[0] << " " << tx[1] << endl;
	cout << ty[0] << " " << ty[1] << endl;
	if (x == y)
	    return tx[b] + g[x][b];//b 以上的值的最xiao。
	for (int j = 20;j >= 0;j--){
		if (fa[x][j] != fa[y][j]){
			nx[0] = nx[1] = ny[0] = ny[1] = INF;
			for (int u=0;u<2;u++)
			    for (int v = 0;v < 2;v++){
			    	nx[v] = min(nx[v],tx[u] + fh[x][j][u][v]);
			    	ny[v] = min(ny[v],ty[u] + fh[y][j][u][v]);
				}
		    tx[0] = nx[0],tx[1] = nx[1],x = fa[x][j];
		    ty[0] = ny[0],ty[1] = ny[1],y = fa[y][j];
		}
	} 
	int lca = fa[x][0];
	cout << lca << endl;
	// when lca is 0 or 1
	cout << f[lca][0] << " " << f[x][1] << " " << f[y][1] << " " << tx[1] << " " << ty[1] << " " << g[lca][0] << endl;
	int ans0 = f[lca][0] - f[x][1] - f[y][1] + tx[1] + ty[1] + g[lca][0]; 
	//       把 x 和 y 两棵子树的数据切掉,换上新数据 
	int ans1 = f[lca][1] - min(f[x][0],f[x][1]) - min(f[y][0],f[y][1]) + min(tx[1],tx[0]) + min(ty[1],ty[0]) + g[lca][1];
	cout << ans0 << " " << ans1 << endl;
	return min(ans0,ans1);
}
signed main(){
	n = read(),m = read(),cin >> s;
	for (int i=1;i<=n;i++)val[i] = read();
	for (int i=1,u,v;i<n;i++){
		u = read(),v = read();
		add(u,v),add(v,u);
		st.insert(make_pair(u,v));
		st.insert(make_pair(v,u));
	}
	dep[0] = 0;
	dfs(1,0),dfs2(1,-1);
	for (int i=1;i<=n;i++){
		fh[i][0][0][0] = INF;
		fh[i][0][0][1] = f[fa[i][0]][1] - min(f[i][0],f[i][1]);
		fh[i][0][1][0] = f[fa[i][0]][0] - f[i][1];
		fh[i][0][1][1] = f[fa[i][0]][1] - min(f[i][0],f[i][1]);
	}
	for (int j=1;j<=20;j++){
		for (int i=1;i<=n;i++){
			int tmp = fa[i][j-1];
			fa[i][j] = fa[tmp][j-1];
			for (int u = 0;u < 2;u++)
			    for (int v = 0;v < 2;v++){
			    	fh[i][j][u][v] = INF;
			    	for (int w = 0;w < 2;w++){
			    		fh[i][j][u][v] = min(fh[i][j][u][v],fh[i][j-1][u][w] + fh[tmp][j-1][w][v]);
					}
				}
		}
	}
	for (int i=1,a,b,x,y;i<=m;i++){
		a = read(),x = read(),b = read(),y = read();
		if (!x && !y && st.find(make_pair(a,b)) != st.end()){
			puts("-1");
			continue;
		}
		printf("%lld\n",solve(a,x,b,y));
	}
    return 0;
}//喵内~
/*
*/
2023/10/5 23:50
加载中...