萌新最短路求助
查看原帖
萌新最短路求助
173660
zhoukangyang楼主2020/8/14 22:24

思路是 构建圆方树 + 倍增 LCA+tarjanLCA + tarjan 求解仙人掌上的最短路

调了一天了,求助。

禁止无意义回复。

#include<bits/stdc++.h>

#define N 20010
#define M 20010
#define ll long long

using namespace std;
int n, m, q, tot, fa[N], dfn[N], low[N], v[N], dep[N], cnt;
int stac[N], stot;
struct node {
	int to, val, next;
} e[M << 1];
map<int, ll> mp[N];
map<int, bool> vis[N];
int edge_id, head[N];
void add_edge(int u, int v, int val) {
	++edge_id;
	e[edge_id].next = head[u];
	e[edge_id].to = v;
	e[edge_id].val = val;
	head[u] = edge_id;
}

int jpfa[22][N];
ll jpval[22][N];
void tarjan(int x) {
	dfn[x] = low[x] = ++cnt, stac[++stot] = x;
	for(int i = head[x]; i; i = e[i].next) {
		if(e[i].to == fa[x]) continue;
		if(!dfn[e[i].to]) fa[e[i].to] = x, v[e[i].to] = e[i].val, tarjan(e[i].to);
		low[x] = min(low[x], low[e[i].to]);
		if(low[e[i].to] != dfn[x] || vis[x][e[i].to]) continue;
		ll ssum = v[x], tsum = 0;
		int gtot = stot;
		for(int i = head[x]; i; i = e[i].next) if(e[i].to == stac[stot]) ssum = e[i].val;
		++tot, fa[tot] = jpfa[0][tot] = x;
		while(gtot) {
			ssum += v[stac[gtot]];
			if(stac[gtot] == e[i].to) {
				--gtot;
				break;
			}
			--gtot;
		}
		int sstot = stot;
		for(stot = gtot + 1; stot <= sstot; stot++) {
			tsum += v[stac[stot]];
			mp[tot - n][stac[stot]] = tsum;
			jpfa[0][stac[stot]] = fa[stac[stot]] = tot, jpval[0][stac[stot]] = min(ssum - tsum, tsum);
			vis[x][stac[stot]] = 1;
		}
		stot = gtot;
	}
	if(low[x] == dfn[x]) jpfa[0][x] = fa[x], jpval[0][x] = v[x], --stot;
}

int dfs(int x) {
	if(dep[x]) return dep[x];
	return dep[x] = dfs(fa[x]) + 1; 
}

void build() {
	for(int i = 1; i <= 18; i++) 
		for(int j = 1; j <= tot; j++) 
			jpfa[i][j] = jpfa[i - 1][jpfa[i - 1][j]], 
			jpval[i][j] = jpval[i - 1][j] + jpval[i - 1][jpfa[i - 1][j]];
}

int A, B, LCA;
ll Ans;
void query(int x, int y) {
	Ans = 0;
	if(dep[x] < dep[y]) swap(x, y);
	for(int i = 18; i >= 0; i--) if(dep[x] - dep[y] >= (1 << i)) Ans += jpval[i][x], x = jpfa[i][x];
	for(int i = 18; i >= 0; i--) 
		if(jpfa[i][x] != jpfa[i][y]) 
			Ans += jpval[i][x] + jpval[i][y], x = jpfa[i][x], y = jpfa[i][y];
	A = x, B = y;
	if(x != y) LCA = jpfa[0][x];
	else LCA = x, A = B = 0;//, Ans -= jpval[0][A] + jpval[0][B];
}

int main() {
	scanf("%d%d%d", &n, &m, &q), tot = n;
	for(int i = 1; i <= m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		add_edge(u, v, w), add_edge(v, u, w);
	}
	dep[1] = 1, tarjan(1);
	for(int i = 2; i <= tot; i++) dfs(i);
	build();
	while(q--) {
		int u, v;
		scanf("%d%d", &u, &v);
		query(u, v);
		if(LCA <= n) printf("%lld\n", Ans + jpval[0][A] + jpval[0][B]);
		else printf("%lld\n", Ans + abs(mp[LCA - n][A] - mp[LCA - n][B]));
	}
	return 0;
}
2020/8/14 22:24
加载中...