Gym - 100015C City Driving
题意:给你一个n个点的树再加上一条边,求询问的两个点的最短路
题解:去掉形成的环中的一条边,这样就变成了一个普通的求树上最短路,求得A1,然后求u到删掉边的u,v到删掉边的v,再加上删掉边的权值,求得A2,求v到删掉边的u,u到删掉边的v,再加上删掉边的权值w,求得A3,取最小值即可
我用的是在线倍增,为什么不用tarjan和rmq,我和他们不太熟啊
多组输入,vector忘记初始化了,爷哭了
代??
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10 ; int n ; int f[maxn], dep[maxn], fa[maxn][20], val[maxn][20] ; bool use[maxn], visit[maxn] ; struct Edge { int from, to, dist, id ; friend bool operator < (const Edge &x, Edge &y) { return x.dist < y.dist ; } }edge[maxn << 1] ; vector<int> v[maxn] ; vector<int> d[maxn] ; int Find(int x) { return x == f[x] ? f[x] : f[x] = Find(f[x]) ; } void kruskal(int n) { for(int i = 1 ; i <= n ; ++ i) f[i] = i ; int cnt = 0 ; for(int i = 1 ; i <= n ; ++ i) { int from = edge[i].from, to = edge[i].to ; int fx = Find(from), fy = Find(to) ; if(fx != fy) { ++ cnt ; use[i] = 1 ; f[fx] = fy ; v[from].push_back(to) ; v[to].push_back(from) ; d[from].push_back(edge[i].dist) ; d[to].push_back(edge[i].dist) ; if(cnt == n - 1) break ; } } } void dfs(int now, int step) { visit[now] = 1 ; dep[now] = step ; for(int i = 0 ; i < v[now].size() ; ++ i) { int to = v[now][i] ; //printf("%d %d\n",now,to) ; if(visit[to] == 0) { fa[to][0] = now ; val[to][0] = d[now][i] ; dfs(to,step+1) ; } } } int LCA(int x, int y) { int ans = 0 ; if(dep[x] < dep[y]) swap(x,y) ; for(int i = 18 ; i >= 0 ; -- i) { if(dep[fa[x][i]] >= dep[y]) { ans += val[x][i] ; x = fa[x][i] ; } } if(x == y) return ans ; for(int i = 18 ; i >= 0 ; -- i) { if(fa[x][i] != fa[y][i]) { ans += val[x][i] + val[y][i] ; x = fa[x][i] ; y = fa[y][i] ; } } ans += val[x][0] + val[y][0] ; return ans ; } int main(int argc, char const *argv[]) { while(scanf("%d",&n) != EOF ) { if(n == 0) break ; memset(use,0,sizeof use) ; memset(visit,0,sizeof visit) ; memset(val,0,sizeof val) ; for(int i = 1 ; i <= n ; ++ i) v[i].clear(), d[i].clear() ; for(int i = 1, from, to, dist ; i <= n ; ++ i) { scanf("%d %d %d",&from,&to,&dist) ; edge[i].from = from + 1 ; edge[i].to = to + 1 ; edge[i].dist = dist ; edge[i].id = i ; } sort(edge+1,edge+1+n) ; kruskal(n) ; Edge noUse ; for(int i = 1 ; i <= n ; ++ i) { if(use[i] == 0) { noUse.from = edge[i].from ; noUse.to = edge[i].to ; noUse.dist = edge[i].dist ; } } fa[1][0] = 0 ; dep[0] = -1 ; dfs(1,0) ; for(int j = 1 ; j <= 18 ; ++ j) { for(int i = 1 ; i <= n ; ++ i) { fa[i][j] = fa[fa[i][j-1]][j-1] ; val[i][j] = val[i][j-1] + val[fa[i][j-1]][j-1] ; } } int q ; scanf("%d",&q) ; while(q --) { int x, y ; scanf("%d %d",&x,&y) ; x ++ ; y ++ ; printf("%d\n",min(LCA(x,y), min(LCA(x,noUse.from) + LCA(y,noUse.to) + noUse.dist, LCA(y,noUse.from) + LCA(x,noUse.to) + noUse.dist ))) ; } } return 0; }
原文地址:https://www.cnblogs.com/wifePI/p/12215593.html
时间: 2024-11-23 03:43:38