首页 > 代码库 > 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类似
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。