哇好久都没上博客了,发道水题。
思路很简单,先建出来最大生成树,在树上跑两点lca,边跑边更新答案即可。
可是刚写出来确实是漏洞百出了。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 50005;
const int P = 20;
int fa[N], jum[N][25], dep[N], qwq[N][P+1], check[N];//P要+1!!不然会爆栈!!
int n, m;
int stot, nex[N*2], h[N], w[N], tov[N*2];
void add ( int u, int v, int ww ) {
tov[++stot] = v;
w[stot] = ww;
nex[stot] = h[u];
h[u] = stot;
}
struct node {
int x, y, z;
} tree[N*2];
bool cmp ( node a, node b ) {
return a.z > b.z;
}
int find ( int a ) {
if ( a != fa[a] ) return fa[a] = find ( fa[a] );
return a;
}
void unionn ( int a, int b ) {
int aa = find ( a );//并查集是把爸爸并起来。。
int bb = find ( b );
fa[aa] = bb;
}
void kruskal ( ) {
int flag = 0;
for ( int i = 1; i <= n; i ++ )
fa[i] = i;
for ( int i = 1; i <= m; i ++ ) {
int xx = find ( tree[i].x );
int yy = find ( tree[i].y );
if ( xx != yy ) {
flag ++;
unionn ( yy, xx );
add ( tree[i].x, tree[i].y, tree[i].z );
add ( tree[i].y, tree[i].x, tree[i].z );
}
if ( flag == n-1 ) break;
}
}
void dfs ( int u, int ff, int d ) {
jum[u][0] = ff;
for ( int p = 1; p <= P; p ++ ) {
jum[u][p] = jum[jum[u][p-1]][p-1];
qwq[u][p] = min ( qwq[jum[u][p-1]][p-1], qwq[u][p-1] );
}
check[u] = 1;
dep[u] = d;
for ( int i = h[u]; i; i = nex[i] ) {
int v = tov[i];
if ( v == ff ) continue;
qwq[v][0] = w[i];
dfs ( v, u, d + 1 );
}
}
int lca ( int u, int v ) {
int ans = 0x3f3f3f3f;
if ( dep[u] < dep[v] ) swap ( u, v );
int t = dep[u] - dep[v];
for ( int p = 0; t; t >>= 1, p ++ )
if ( t & 1 ) {
ans = min ( ans, qwq[u][p] );
u = jum[u][p];
}
if ( u == v ) return ans;//!!!真的很重要不然会多跳一步对了3组真是运气好
for ( int p = P; p >= 0; p -- )
if ( jum[u][p] != jum[v][p] ) {
ans = min ( ans, min ( qwq[v][p], qwq[u][p] ) );
u = jum[u][p], v = jum[v][p];
}
ans = min ( ans, min ( qwq[v][0], qwq[u][0] ) );
return ans;
}
int main ( ) {
scanf ( "%d%d", &n, &m );
for ( int i = 1; i <= m; i ++ ) {
int x, y, z;
scanf ( "%d%d%d", &tree[i].x, &tree[i].y, &tree[i].z );
}
sort ( tree+1, tree+1+m, cmp );
kruskal ( );
int q, u, v;
memset ( qwq, 127, sizeof ( qwq ) );
for ( int i = 1; i <= n; i ++ )
dep[i] = 1;
for ( int i = 1; i <= n; i ++ )
if ( !check [i] )
dfs ( i, i, 1 );
scanf ( "%d", &q );
for ( int i = 1; i <= q; i ++ ) {
scanf ( "%d%d", &u, &v );
if ( find ( u ) != find ( v ) ) printf ( "-1\n" );
else printf ( "%d\n", lca ( u, v ) );
}
return 0;
}
调了好几天改出来一大堆错。。
继续努力!!