裸題-UVA11354_最小瓶頸路_LCA(兩種寫法)
阿新 • • 發佈:2018-12-13
(有任何問題歡迎留言或私聊 && 歡迎交流討論哦
Catalog
Problem:
原題目描述在最下面。
給定一個個點圖,次詢問最小瓶頸路。
最小瓶頸路就是在兩個結點之間求一條最長邊最短的路徑,而次小生成樹則是所有生成樹中權值排名第二的生成樹(可以和最小生成樹相等)(當然也有一個問題是求嚴格的次小生成樹, 那麼這個就不同了)
Solution:
裸題啊,自己敲一遍練練手咯
倍增加隨便搞搞。
性質1: 最小瓶頸路的值一定在上。
所以就在上跑一遍樹上倍增,記錄最大權值。
詢問的話,就在求LCA的同時,記錄最大邊權即可。
AC_Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <ctime>
#include <iostream>
#define lson(x) cw[x].l
#define rson(x) cw[x].r
using namespace std;
typedef long long LL;
const int MXN = 1e5 + 5;
const int MXE = 6e5 + 5;
const int INF = 0x3f3f3f3f;
int n, m;
int fa[MXN], FA[MXN], up[MXN][23], dis[MXN][23], dep[MXN];
int head[MXN], tot;
struct lp{
int v, w, nex;
}cw[MXE];
struct node{
int u, v, w;
}edge[MXE];
void init() {
tot = -1;
memset(head, -1, sizeof(head));
memset(dis, 0, sizeof(dis));
}
void dfs(int u,int ba,int d) {
fa[u] = up[u][0] = ba;
dep[u] = d;
for(int i = 1, cf; i < 20; ++i) {
cf =up[u][i-1];
up[u][i] = up[cf][i-1];
dis[u][i] = max(dis[u][i-1],dis[cf][i-1]);
}
for(int i = head[u]; ~i; i = cw[i].nex) {
int v = cw[i].v;
if(v == ba) continue;
dis[v][0] = cw[i].w;
up[v][0] = u;
dfs(v, u, d+1);
}
}
/*int LCA(int x,int y) {
int ans = 0;
if(dep[x] < dep[y]) swap(x, y);
int k = dep[x] - dep[y];
for(int i = 0; i < 20; ++i) {
if((1<<i)&k){
ans = max(ans, dis[x][i]);
x = up[x][i];
}
}
if(x != y){
for(int i = 19; i >= 0; --i) {
if(up[x][i] != up[y][i]) {
ans = max(ans, dis[x][i]);
ans = max(ans, dis[y][i]);
x = up[x][i]; y = up[y][i];
}
}
ans = max(ans, max(dis[x][0],dis[y][0]));
}
return ans;
}*/
int LCA(int x,int y) {
int ans = 0;
if(dep[x] < dep[y]) swap(x, y);
for(int i = 19; i >= 0; --i) {
if(dep[up[x][i]] >= dep[y]) {
ans = max(ans, dis[x][i]);
x = up[x][i];
}
}
if(x != y){
for(int i = 19; i >= 0; --i) {
if(up[x][i] != up[y][i]) {
ans = max(ans, dis[x][i]);
ans = max(ans, dis[y][i]);
x = up[x][i]; y = up[y][i];
}
}
ans = max(ans, max(dis[x][0],dis[y][0]));
}
return ans;
}
void add_edge(int u,int v,int w) {
cw[++tot].v = v; cw[tot].w = w; cw[tot].nex = head[u];
head[u] = tot;
cw[++tot].v = u; cw[tot].w = w; cw[tot].nex = head[v];
head[v] = tot;
}
bool cmp(node &a, node &b) {
return a.w < b.w;
}
int Fi(int x) {
return FA[x] == x? x: FA[x] = Fi(FA[x]);
}
int fuck = 0;
void solve() {
if(fuck) printf("\n");
init();
for(int i = 0; i < m; ++i) {
scanf("%d%d%d", &edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge, edge + m, cmp);
int CNT = 0;
for(int i = 1; i <= n; ++i) FA[i] = i;
for(int i = 0; i < m; ++i) {
int pa = Fi(edge[i].u), pb = Fi(edge[i].v);
if(pa == pb) continue;
FA[pb] = pa;
add_edge(edge[i].u,edge[i].v,edge[i].w);
CNT ++;
if(CNT == n - 1) break;
}
up[1][0] = 1;
//dis[1][0] = INF;
dfs(1, 1, 1);
int q, u, v;scanf("%d", &q);
while(q--) {
scanf("%d%d", &u, &v);
printf("%d\n", LCA(u, v));
}
fuck++;
}
int main(int argc, char const *argv[]){
while(~scanf("%d%d", &n, &m)) solve();
return 0;
}