제출 #498103

#제출 시각아이디문제언어결과실행 시간메모리
498103IerusEvacuation plan (IZhO18_plan)C++17
100 / 100
676 ms64508 KiB
#include<bits/stdc++.h>

using namespace std;
#pragma GCC optimize ("unroll-loops,Ofast,O3")
#pragma GCC target("avx,avx2,fma")
#define F first
#define S second
#define sz(x) (int)x.size()
#define pb push_back
#define NFS ios_base::sync_with_stdio(0) , cin.tie(0) , cout.tie(0) ;
const int N = 5e5+777;
int n, m;
vector<pair<int,int>> g[N];
struct Dsu{
	int n;
	vector<int> p, sm;
	Dsu(int _n){
		n = _n;
		p.resize(n+2);
		sm.resize(n+2);
		for(int i = 1; i <= n; ++i){
			p[i] = i;
			sm[i] = i;
		}
	}
	int get(int v){
		if(p[v] == v) return v;
		return p[v] = get(p[v]);
	}
	bool merge(int x, int y){
		x = get(x), y = get(y);
		if(x == y){
			return false;
		}
		if(sm[x] < sm[y]){
			swap(x, y);
		}
		sm[x] += sm[y];
		p[y] = x;
		return true;
	}
}dsu(N);
struct node{
	int w, v, u;
}edge[N];
vector<int> d(N, INT_MAX);
inline void dijikstra(){
	set<pair<int,int>> st;
	int t; cin >> t;
	for(int i = 1; i <= t; ++i){
		int v; cin >> v;
		st.insert({d[v]=0, v});
	}
	while(!st.empty()){
		int v = st.begin() -> S;
		st.erase(st.begin());
		for(auto to : g[v]){
			if(d[to.F] > d[v] + to.S){
				st.erase({d[to.F], to.F});
				st.insert({d[to.F]=d[v]+to.S,to.F});
			}
		}
	}
}
const int LG = 18;
int tin[N], tout[N], timer, up[N][LG+2], mn[N][LG+2], lev[N];
void dfs(int v, int p, int w = 0){
	lev[v] = lev[p] + 1;
	up[v][0] = p;
	mn[v][0] = w;
	for(int L = 1; L <= LG; ++L){
		up[v][L] = up[up[v][L-1]][L-1];
		mn[v][L] = min(mn[v][L-1], mn[up[v][L-1]][L-1]);
	}
	tin[v] = ++timer;
	for(auto to : g[v]){
		if(to.F != p){
			dfs(to.F, v, to.S);
		}
	}
	tout[v] = timer;
}
bool upper (int a, int b) {
	return tin[a] <= tin[b] && tout[b] <= tout[a];
}
int lca (int a, int b) {
	if (upper(a, b))  return a;
	if (upper(b, a))  return b;
	for (int i = LG; i >= 0; --i)
		if (!upper (up[a][i], b))
			a = up[a][i];
	return up[a][0];
}
int get(int x, int y){
	int ans = d[x];
	for(int k = LG; k >= 0; k--){
		if(lev[x] - (1<<k) >= lev[y]){
	    	ans = min(ans, mn[x][k]);
	    	x = up[x][k];
		}
	}
  return ans;
}
void precalc(){
	dijikstra();
	for(int i = 1; i <= n; ++i){
		g[i].clear();
	}
	priority_queue<tuple<int,int,int>> pq;
	for(int i = 1; i <= m; ++i){
		edge[i].w = min(d[edge[i].v], d[edge[i].u]);
		pq.push(make_tuple(edge[i].w, edge[i].v, edge[i].u));
	}
	while(!pq.empty()){
		int x, y, w;
		tie(w, x, y) = pq.top();
		pq.pop();
		if(dsu.merge(x, y)){
			g[x].pb({y, w});
			g[y].pb({x, w});
		}
	}
	dfs(1, 1);
}
int main(){NFS;
	cin >> n >> m;
	for(int i = 1; i <= m; ++i){
		cin >> edge[i].v >> edge[i].u >> edge[i].w;
		g[edge[i].v].pb({edge[i].u,edge[i].w});
		g[edge[i].u].pb({edge[i].v,edge[i].w});
	}
	precalc();
	int que; cin >> que;
	for(int x, y; que--;){
		cin >> x >> y;
		int p = lca(x, y);
		int res1 = get(x, p);
		int res2 = get(y, p);
		cout << min(res1, res2) << '\n';
	}
};
/*
9 12
1 9 4
1 2 5
2 3 7
2 4 3
4 3 6
3 6 4
8 7 10
6 7 5
5 8 1
9 5 7
5 4 12
6 8 2
2
4 7
5
1 6
5 3
4 8
5 8
1 5
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...