不开O2 85pts WA14,15,19
开O2 TLE 10pts
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAXN 10050
int n , m , q , cnt , head[MAXN] , lg[105] , dep[MAXN] , fa[MAXN][105] , un[MAXN] , ms[MAXN][105];
bool vis[MAXN];
struct Edge {
int to , next , maxn;
}edge[MAXN*10];
struct Road {
int u , v , maxn;
}r[MAXN*5];
void add (int in , int ou , int maxn) // 前向星
{
++ cnt;
edge[cnt] = {ou , head[in] , maxn};
head[in] = cnt;
}
int find (int x) // 查询
{
if(un[x] == x) return x;
return un[x] = find(un[x]);
}
void unionn (int fas , int son) // 并查集合并
{
fas = find(fas) , son = find(son);
if(fas != son)
un[son] = fas;
}
void dfs (int now , int fat , int maxn)
{
vis[now] = true;
fa[now][0] = fat , dep[now] = dep[fat] + 1 , ms[now][0] = maxn;
for(int i = 1 ; i <= lg[dep[now]] ; i ++)
{
fa[now][i] = fa[fa[now][i-1]][i-1]; // 求祖先
ms[now][i] = min (ms[now][i-1] , ms[fa[now][i-1]][i-1]); // 倍增求最小值
}
for(int i = head[now] ; i ; i = edge[i].next)
{
const int to = edge[i].to;
if(!vis[to] && to != fat)
dfs (to , now , edge[i].maxn); // 继续便利
}
}
int ask (int x , int y) // LCA
{
if(find(x) != find(y)) return -1; // 不连通
int ans = 0x3f3f3f3f;
if(dep[x] < dep[y]) swap (x , y); // 保证x不比y浅
while (dep[x] > dep[y]){ // 倍增
ans = min (ans , ms[x][lg[dep[x] - dep[y]]]); // 统计答案
x = fa[x][lg[dep[x] - dep[y]]]; // 能跳就跳
}
if(x == y)
return ans;
for(int i = lg[dep[x]] ; i >= 0 ; i --) // 倍增
if(fa[x][i] != fa[y][i])
{
ans = min (ans , min (ms[x][i] , ms[y][i]));
x = fa[x][i];
y = fa[y][i];
}
return min (ans , min(ms[x][0] , ms[y][0])); // 返回答案
}
bool cmp (Road a , Road b){
return a.maxn > b.maxn;
}
signed main()
{
memset (ms , 0x3f , sizeof ms);
cin >> n >> m;
for(int i = 1 ; i <= n+5 ; i ++) // init
un[i] = i;
for(int i = 1 ; i <= m ; i ++) // Read
{
int x , y , z;
cin >> x >> y >> z;
r[i] = {x , y , z};
}
for(int i = 2 ; i <= n ; i ++) // 求每一个数 log2 的值
lg[i] = lg[i-1] + (int)(1 << (lg[i-1]+1) == i);
sort (r+1 , r+1+m , cmp);
for(int i = 1 ; i <= m ; i ++) // 求生成树
if(find(r[i].u) != find(r[i].v))
{
unionn (r[i].u , r[i].v);
add (r[i].u , r[i].v , r[i].maxn);
add (r[i].v , r[i].u , r[i].maxn);
}
for(int i = 1 ; i <= n ; i ++)
if(!vis[i])
dfs (i , 0 , 0x3f3f3f3f); // 遍历
cin >> q;
while (q --)
{
int x , y;
cin >> x >> y;
printf("%d\n",ask(x,y)); // LCA
}
return 0;
}
谢谢大佬!!!