[题解] uva 11354 Bond(kruskal最小生成树+倍增LCA)

- 传送门 -

 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2339

# 11354 - Bond Time limit: 8.000 seconds | [Root](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=0) | [![Submit](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_submit.png "Submit")](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=submit_problem&problemid=2339&category=) [![Problem Stats](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_stats.png "Problem Stats")](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=problem_stats&problemid=2339&category=) [![uDebug](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_debug.png)](https://www.udebug.com/UVa/11354) [![Download as PDF](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_pdf.png "Download as PDF")](https://uva.onlinejudge.org/external/113/11354.pdf) | ###(题面见pdf)
  ### - 题意 -  求图中两点间路径最大值(经过的权值最大的一条路)的最小值.   ### - 思路 -  即最小瓶颈路, 因为最小瓶颈路是在最小生成树上的, 我们先求出最小生成树, 然后因为询问和点数太多, 不能暴搜乱搞, 就在树上来一发LCA啦~    细节见代码.   ### - 代码 - ```c++ #include #include #include using namespace std;

const int N = 5e4 + 5;
const int M = 1e5 + 5;
const int inf = 0x7fffffff;

struct edge {
int x, y, v;
}W[M];

int D[N], ANC[N][18], MA[N][18];
int HD[N], NXT[M], TO[M], V[M];
int F[N];
int n, m, q, cnt, sz, tot;

bool cmp (edge a, edge b) { return a.v < b.v; }

void init() {
sz = cnt = tot = 0;
memset(ANC, 0, sizeof (ANC));
memset(MA, 0, sizeof (MA));
memset(HD, 0, sizeof (HD));
memset(D, 0, sizeof (D));
for (int i = 1; i <= n; ++i)
F[i] = i;
}

void add(int x, int y, int v) {
TO[++tot] = y; NXT[tot] = HD[x]; HD[x] = tot; V[tot] = v;
TO[++tot] = x; NXT[tot] = HD[y]; HD[y] = tot; V[tot] = v;
}

int find(int x) { return x == F[x] ? x : F[x] = find(F[x]); }

void kruskal() {
for (int i = 0; i < m; ++i) {
int fx = find(W[i].x), fy = find(W[i].y);
if (fx == fy) continue;
cnt ++;
F[fx] = fy;
add(W[i].x, W[i].y, W[i].v);
if (cnt == n - 1) break;
}
}

void dfs(int x) {
for (int i = 1; i <= 16; ++i) {
ANC[x][i] = ANC[ANC[x][i-1]][i-1];
MA[x][i] = max(MA[x][i-1], MA[ANC[x][i-1]][i-1]);
}
for (int i = HD[x]; i; i = NXT[i]) {
int v = TO[i];
if (v != ANC[x][0]) {
D[v] = D[x] + 1;
ANC[v][0] = x;
MA[v][0] = V[i];
dfs(v);
}
}
}

void lca(int x, int y) {
int ans = -inf;
if (D[x] < D[y]) swap(x, y);
for (int i = 16; i >= 0; --i)
if (D[ANC[x][i]] >= D[y]) {
ans = max(ans, MA[x][i]);
x = ANC[x][i];
}
if (x != y) {
for (int i = 16; i >= 0; --i)
if (ANC[x][i] != ANC[y][i]) {
ans = max(ans, MA[x][i]);
ans = max(ans, MA[y][i]);
x = ANC[x][i];
y = ANC[y][i];
}
ans = max(ans, MA[x][0]);
ans = max(ans, MA[y][0]);
}
printf("%d\n", ans);
}

int main() {
int cas = 0;
while (scanf("%d%d", &n, &m) != EOF) {
if (cas) printf("\n");
else cas ++;
init();
for (int i = 0; i < m; ++i)
scanf("%d%d%d", &W[i].x, &W[i].y, &W[i].v);
sort(W, W + m, cmp);
kruskal();
for (int i = 1; i <= n; ++i)
if (!D[i]) dfs(i);
scanf("%d", &q);
for (int i = 1, x, y; i <= q; ++i) {
scanf("%d%d", &x, &y);
lca(x, y);
}
}
return 0;
}

posted @ 2017-08-14 21:27  lstttt  阅读(180)  评论(0编辑  收藏  举报