首页 > 代码库 > UVa 11354 Bond 最小生成树+LCA倍增
UVa 11354 Bond 最小生成树+LCA倍增
题目来源:UVa 11354 Bond
题意:n个点m条边的图 q次询问 找到一条从s到t的一条边 使所有边的最大危险系数最小
思路:使最大的危险系数尽量小 答案是最小生成树上的边 然后用LCA倍增法记录s和t到他们最近公共祖先的最大值
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 50010; const int INF = 0x3f3f3f3f; int anc[maxn][30], maxcost[maxn][30]; int fa[maxn], L[maxn], cost[maxn], vis[maxn], f[maxn]; int n, m; int first[maxn], cnt; struct edge { int u, v, w, next; }e[maxn*2], e2[maxn*8]; bool cmp(edge a, edge b) { return a.w < b.w; } void AddEdge(int u, int v, int w) { e2[cnt].v = v; e2[cnt].w = w; e2[cnt].next = first[u]; first[u] = cnt++; e2[cnt].v = u; e2[cnt].w = w; e2[cnt].next = first[v]; first[v] = cnt++; } void pre() { for(int i = 1; i <= n; i++) { anc[i][0] = fa[i]; maxcost[i][0] = cost[i]; for(int j = 1; (1<<j) < n; j++) anc[i][j] = -1; } for(int j = 1; (1<<j) < n; j++) for(int i = 1; i <= n; i++) if(anc[i][j-1] != -1) { int a = anc[i][j-1]; anc[i][j] = anc[a][j-1]; maxcost[i][j] = max(maxcost[i][j-1], maxcost[a][j-1]); } } int query(int p, int q) { int tmp, log, i; if(L[p] < L[q]) swap(p, q); for(log = 1; (1<<log) <= L[p]; log++); log--; int ans = -INF; for(int i = log; i >= 0; i--) if(L[p] - (1<<i) >= L[q]) { ans = max(ans, maxcost[p][i]); p = anc[p][i]; } if(p == q) return ans; for(int i = log; i >= 0; i--) { if(anc[p][i] != -1 && anc[p][i] != anc[q][i]) { ans = max(ans, maxcost[p][i]); ans = max(ans, maxcost[q][i]); p = anc[p][i]; q = anc[q][i]; } } ans = max(ans, cost[p]); ans = max(ans, cost[q]); return ans; } void dfs(int u) { for(int i = first[u]; i != -1; i = e2[i].next) { int v = e2[i].v; if(vis[v]) continue; vis[v] = 1; fa[v] = u; cost[v] = e2[i].w; L[v] = L[u]+1; dfs(v); } } int find(int x) { if(f[x] != x) return f[x] = find(f[x]); return x; } int main() { int cas = 0; while(scanf("%d %d", &n, &m) != EOF) { memset(first, -1, sizeof(first)); memset(vis, 0, sizeof(vis)); cnt = 0; for(int i = 0; i < m; i++) { scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].w); } sort(e, e+m, cmp); for(int i = 0; i <= n; i++) f[i] = i; int sum = 0; for(int i = 0; i < m; i++) { int u = e[i].u; int v = e[i].v; int x = find(u); int y = find(v); if(x != y) { sum++; f[x] = y; AddEdge(e[i].u, e[i].v, e[i].w); } } fa[1] = -1; cost[1] = 0; L[1] = 0; vis[1] = 1; dfs(1); pre(); int q; scanf("%d", &q); if(cas++) printf("\n"); while(q--) { int u, v; scanf("%d %d", &u, &v); printf("%d\n", query(u, v)); } } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。