玄关85pts求救大佬
查看原帖
玄关85pts求救大佬
1098596
WhiteNight__楼主2024/7/23 21:37

不开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;
}

谢谢大佬!!!

2024/7/23 21:37
加载中...