首页 > 代码库 > UVA 11354 Bond 瓶颈路 最小生成树+LCA类似

UVA 11354 Bond 瓶颈路 最小生成树+LCA类似

题目链接:点击打开链接

题意:

给定n个点m条边的无向图

下面m行是(u,v) 和边权

下面q个询问

(u, v)

在这两个点间找一条路径使得这个路径上最大的边权最小。

数据保证询问的2个点之间一定存在路径


思路:

求瓶颈路,最小生成树跑一下。

然后求lca的代码里加入边权。

因为要使得最大的边权最小,所以用最小生成树的krusal算法,

正确性证明:

我们现在有联通块G,一个孤立点u,以及G与u之间的一些边,则显然我们选择边权最小的一条边把2个联通块连接。

这个过程就是krusal。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <map>
#include <algorithm>
#include <set>
#include <queue>
using namespace std;
#define N 50010
#define M 100010
inline void rd(int &n){
	n = 0;
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') n *= 10, n += (c - '0'),c = getchar();
}
struct Edge {
    int from, to, dis, nex;
}edge[M<<1], hehe[M<<1];
bool cmp(Edge a, Edge b){return a.dis < b.dis;}
int head[N], edgenum;
void add(int u, int v, int d){
    Edge E = {u,v,d,head[u]};
    edge[edgenum] = E;
    head[u] = edgenum++;
}
int f[N];
int find(int x){return x==f[x] ? x : f[x] = find(f[x]);}
bool Union(int x, int y){
    int fx = find(x), fy = find(y);
    if(fx == fy)return false;
    if(fx>fy)swap(fx,fy);
    f[fx] = fy;
    return true;
}
int fa[N][20], dep[N], cost[N][20]; //cost[u][i]表示u点到u的第2^i次父亲 路径上最大边权
void bfs(int root){
    queue<int>q;
    fa[root][0] = root; dep[root] = 0;
    cost[root][0] = 0;
    q.push(root);
    while(!q.empty()) {
        int u = q.front(); q.pop();
        for(int i = 1; i < 20; i++) {
            fa[u][i] = fa[fa[u][i-1]][i-1];
            cost[u][i] = max(cost[u][i-1], cost[fa[u][i-1]][i-1]);
        }
        for(int i = head[u]; ~i; i = edge[i].nex) {
            int v = edge[i].to; if(v == fa[u][0])continue;
            dep[v] = dep[u]+1; fa[v][0] = u; cost[v][0] = edge[i].dis;
            q.push(v);
        }
    }
}
int work(int x, int y){
    int ans = 0;
    if(dep[x] < dep[y]) swap(x, y);
    for(int i = 0; i < 20; i++) if((dep[x]-dep[y])&(1<<i)) {
        ans = max(ans, cost[x][i]);
        x = fa[x][i];
    }
    if(x == y)return ans;
    for(int i = 19; i >= 0; i--)if(fa[x][i]!=fa[y][i]) {
        ans = max(ans, max(cost[x][i], cost[y][i]));
        x = fa[x][i], y = fa[y][i];
    }
	ans = max(ans, cost[x][0]);
	ans = max(ans, cost[y][0]);
    return ans;
}
int main(){
    int i, j, u, v, d, query, n, m, fir = 0;
	while(~scanf("%d %d",&n,&m)){
        if(fir++)puts("");
        memset(head, -1, sizeof head); edgenum = 0;
        for(i = 1; i <= n; i++) f[i] = i;
        for(i = 0; i < m; i++){
            rd(hehe[i].from); rd(hehe[i].to); rd(hehe[i].dis);
        }
        sort(hehe, hehe + m, cmp);
        int siz = 0;
        for(int i = 0; i < m && siz < n; i++) {
            if(Union(hehe[i].from, hehe[i].to)){
                siz++;
                add(hehe[i].from, hehe[i].to, hehe[i].dis);
                add(hehe[i].to, hehe[i].from, hehe[i].dis);
            }
        }
        bfs(1);
        rd(query);
        while(query--){
            rd(u); rd(v);
            printf("%d\n", work(u, v));
        }
	}
	return 0;
}
/*
8 7
1 2 1
1 3 2
3 7 3
7 8 10
2 4 2
2 5 4
5 6 6
99
1 2
2 6
6 4
6 8
4 5
1 7
3 8


ans:
1
6
6
10
4
3
10
*/


UVA 11354 Bond 瓶颈路 最小生成树+LCA类似