刚学OI, 爆0求助
  • 板块P4220 [WC2018] 通道
  • 楼主Zcus
  • 当前回复15
  • 已保存回复15
  • 发布时间2021/2/20 10:02
  • 上次更新2023/11/5 03:00:21
查看原帖
刚学OI, 爆0求助
33339
Zcus楼主2021/2/20 10:02

有好哥哥能看一眼吗, 实在看不出来有什么问题了

/*
Arthor: Ender_zzm
E-mail: ender-zzm@foxmail.com
Blog: oi.ender-zzm.pro
*/

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

//#define int long long
//#define FILE
#define fi first
#define se second
#define vec vector
#define pb push_back
#define pii pair<int, int>
#define mp make_pair
#define ri read<int>
#define rl read<long long>
#define debug(x) cout << #x << " = " << x << endl
#define For(i, x, y) for (int i = x; i <= y; i++) 
#define Rep(i, x, y) for (int i = x; i >= y; i--) 
#define file(FILE_NAME) freopen(FILE_NAME".in", "r", stdin), freopen(FILE_NAME".out", "w", stdout)
#define filein(FILE_NAME) freopen(FILE_NAME".in", "r", stdin);
#define fileout(FILE_NAME) freopen(FILE_NAME".out", "w", stdout);

template<class T> inline bool Chkmax(T& x, const T& y) { return x < y ? x = y, true : false; }
template<class T> inline bool Chkmin(T& x, const T& y) { return x > y ? x = y, true : false; }

#define int long long
const int maxn = 2e6 + 30;
const int maxm = 2e6 + 30;

int ans = 0;

int n; 
struct edge
{
	int net[maxm], head[maxn], to[maxm], tot = 1, cost[maxm];
	void add(int x, int y, int z) 
	{
		net[++tot] = head[x]; head[x] = tot; to[tot] = y; cost[tot] = z;
		net[++tot] = head[y]; head[y] = tot; to[tot] = x; cost[tot] = z;
	}
}T1, T2, T3, DT;

vec<int> G[maxn];

//预处理T1的dis, 放在T2上, 然后对T3边分治, 将贡献丢到T2上, 对点集做虚树, 合并直径求答案
int dis[maxn];
int val[maxn];
int ffT1[32][maxn], deepT1[maxn], disT1[maxn], dfn[maxn], cnt;
void init(int x, int fa) 
{
	dfn[x] = ++cnt;
	deepT1[x] = deepT1[fa] + 1;
	ffT1[0][x] = fa;
	for (int i = T1.head[x]; i; i = T1.net[i]) 
	{
		int v = T1.to[i];
		if (v == fa) continue;
		dis[v] = dis[x] + T1.cost[i];
		disT1[v] = dis[v];
		init(v, x);
	}
}
int T1Lca(int x, int y) 
{
	if (deepT1[x] < deepT1[y]) swap(x, y);
	int d = deepT1[x] - deepT1[y];
	for (int i = 0; i <= 20; i++) if (d & (1 << i)) x = ffT1[i][x];
	if (x == y) return x;
	for (int i = 20; i >= 0; i--) if (ffT1[i][x] != ffT1[i][y]) x = ffT1[i][x], y = ffT1[i][y];
//	cout << "sdfasdas" << endl;
//	debug(x);
//	debug(ffT1[0][x]);
	return ffT1[0][x];
}
int nn;
void rebuild(int x, int fa) // 对T3_rebuild
{
	int las = x;
	for (int i = T3.head[x]; i; i = T3.net[i]) 
	{
		int v = T3.to[i];
		if (v == fa) continue;
		rebuild(v, x);
		++nn;
		DT.add(las, nn, 0); DT.add(nn, v, T3.cost[i]); las = nn;;
	}
}
int ff[33][maxn], deep[maxn];
void init2(int x, int fa)  // 对T2进行做虚树的预处理
{
	ff[0][x] = fa;
	deep[x] = deep[fa] + 1;
	for (int i = T2.head[x]; i; i = T2.net[i]) 
	{
		int v = T2.to[i];
		if (v == fa) continue;
		dis[v] = dis[x] + T2.cost[i];
		init2(v, x);
	}
}
int Lca(int x, int y) 
{
	if (deep[x] < deep[y]) swap(x, y);
	int d = deep[x] - deep[y];
	for (int i = 0; i <= 20; i++) if (d & (1 << i)) x = ff[i][x];
	if (x == y) return x;
	for (int i = 20; i >= 0; i--) if (ff[i][x] != ff[i][y]) x = ff[i][x], y = ff[i][y];
	return ff[0][x];
}
int vis[maxn], size[maxn], maxx, id;
void Geted(int x, int fa, int SZ) 
{
	size[x] = 1;
	for (int i = DT.head[x]; i; i = DT.net[i]) 
	{
		int v = DT.to[i];
		if (v == fa || vis[i]) continue;
		size[x] += size[v];
		if (max(size[v], SZ - size[v]) < maxx) maxx = max(size[v], SZ - size[v]), id = i;
	}
}
vec<int> p;
int col[maxn], ysh[maxn];
void Getdis(int x, int fa, int dis, int col) 
{
	size[x] = 1;
	if (x <= n) ysh[x] = dis;
	if (x <= n) p.pb(x); ::col[x] = col;
	for (int i = DT.head[x]; i; i = DT.net[i]) 
	{
		int v = DT.to[i];
		if (v == fa || vis[i]) continue;
		Getdis(v, x, dis + DT.cost[i], col);
		size[x] += size[v];
	}
}
namespace super
{
	int st[maxn], tot, root;
	vec<int> G[maxn];


	void add(int x, int y) 
	{
		G[x].pb(y); G[y].pb(x);
	}
	int cmp(int x, int y) 
	{
		return dfn[x] < dfn[y];
	}
	void build() 
	{
//		for (int i = 2; i <= T1.tot; i += 2) 
//		{
//			add(T1.to[i], T1.to[i ^ 1]);
//		}
//		root = 1;
//		return;
	//	for (int i = 0; i < p.size(); i++) 
	//	{
	//		cout << p[i] << " ";
	//	}
	//	cout << endl;
		st[++tot] = 1;
		for (int i = 0; i < p.size(); i++) 
		{
			if (!tot) 
			{
				st[++tot] = p[i]; continue;
			}
			if (p[i] == 1) continue;
		//	debug(p[i]); debug(st[tot]);
			int LCA = T1Lca(p[i], st[tot]);
			if (LCA == st[tot]) 
			{
				st[++tot] = p[i]; continue;
			}
	//		cout << "akakakaa " << p[i] << " " << st[tot] << " " << LCA << endl;
	//		debug(LCA);
			while (tot > 1 && dfn[st[tot - 1]] > dfn[LCA]) add(st[tot - 1], st[tot]), tot--;
			if (st[tot - 1] != LCA) add(LCA, st[tot]), st[tot] = LCA;
			else add(LCA, st[tot--]);
			st[++tot] = p[i];
		}
		root = st[1];
		while (tot > 1) add(st[tot - 1], st[tot]), tot--;
		tot = 0;
	}
	int Dis(int x, int y) 
	{
		int lca = T1Lca(x, y);
		return dis[x] + dis[y] - 2 * dis[Lca(x, y)] + val[x] + val[y] + ysh[x] + ysh[y];
	}
	struct use
	{
		int dis, x, y; // x 是 o
	}oo[maxn], ob[maxn], bb[maxn];
	void dfs(int x, int fa) 
	{
	//	debug(x); cout.flush();
		oo[x].dis = ob[x].dis = bb[x].dis = -1;
		oo[x].x = oo[x].y = ob[x].x = ob[x].y = bb[x].x = bb[x].y = 0;
		if (col[x] == 0) oo[x].dis = ysh[x] * 2 + val[x] * 2, oo[x].x = x, oo[x].y = x;
		if (col[x] == 1)  bb[x].dis = ysh[x] * 2 + val[x] * 2, bb[x].x = x, bb[x].y = x;
		for (int i = 0; i < G[x].size(); i++) 
		{
			int v = G[x][i];
			if (v == fa) continue;
			dfs(v, x);
			//更新oo
			vec<int> asd;
			asd.pb(oo[x].x); asd.pb(oo[x].y); asd.pb(oo[v].x); asd.pb(oo[v].y);
			asd.pb(ob[x].x); asd.pb(ob[x].y); asd.pb(ob[v].x); asd.pb(ob[v].y);
			asd.pb(bb[x].x); asd.pb(bb[x].y); asd.pb(bb[v].x); asd.pb(bb[v].y);
			for (int i = 0; i < 11; i++) 
			{
				if (asd[i] == 0) continue;
				for (int j = i; j < 11; j++) 
				{
					if (T1Lca(asd[i], asd[j]) == x && col[asd[i]] != col[asd[j]]) 
					{
						ans = max(ans, Dis(asd[i], asd[j]) - 2 * disT1[x]);
					}
					if (asd[j] == 0) continue;
					if (col[asd[j]] == -1) continue;
					if (col[asd[j]] == col[asd[i]]) 
					{
						if (col[asd[i]] == 0) {
							if (Chkmax(oo[x].dis, Dis(asd[i], asd[j]))) oo[x].x = asd[i], oo[x].y = asd[j];
						}
						else 
							if (Chkmax(bb[x].dis, Dis(asd[i], asd[j]))) bb[x].x = asd[i], bb[x].y = asd[j];
					}
					else 
					{
						if (Chkmax(ob[x].dis, Dis(asd[i], asd[j]))) ob[x].x = asd[i], ob[x].y = asd[j];
					}
				}
			}
		}
		ans = max(ans, ob[x].dis - 2 * disT1[x]);
		G[x].clear();
	}
	void solve() 
	{
		sort(p.begin(), p.end(), cmp);
		build();
		dfs(root, 0);
	}
}
void Solve(int x, int SZ) 
{
	if (SZ == 1) return;
	maxx = nn + 1;
	Geted(x, 0, SZ);
	int xx = DT.to[id], yy = DT.to[id ^ 1]; vis[id] = vis[id ^ 1] = 1;
	Getdis(xx, 0, 0, 0); Getdis(yy, 0, DT.cost[id], 1); 
	super :: solve();
	memset(ysh, 0, sizeof ysh);
	//memset(col, -1, sizeof col);
	for (int i = 0; i < p.size(); i++) col[p[i]] = -1;
	p.clear();
	Solve(xx, size[xx]); Solve(yy, size[yy]);
}
signed main() 
{
	filein("11");
	fileout("1");
	ios :: sync_with_stdio(0); cin.tie(0);
	cin >> n; nn = n;
	memset(col, -1, sizeof col);
	For (i, 1, n - 1) 
	{
		int x, y, z;
		cin >> x >> y >> z;
		T1.add(x, y, z);
	}
	For (i, 1, n - 1) 
	{
		int x, y, z;
		cin >> x >> y >> z;
		T2.add(x, y, z);
	}
	For (i, 1, n - 1) 
	{
		int x, y, z;
		cin >> x >> y >> z;
		T3.add(x, y, z);
	}
	init(1, 0);
	For (i, 1, n) val[i] += dis[i];
	rebuild(1, 0);
	dis[1] = 0;
	init2(1, 0);
	for (int i = 1; i <= 20; i++) 
		for (int j = 1; j <= n; j++) 
			ff[i][j] = ff[i - 1][ff[i - 1][j]],
			ffT1[i][j] = ffT1[i - 1][ffT1[i - 1][j]];
	Solve(1, nn);
	cout << ans << endl;
	return 0;
}


2021/2/20 10:02
加载中...