構造最大生成樹

P1967 貨車運輸

AC代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int N = 10005, M = 50005, K = 15;
int head[N], ver[N << 1], edge[N << 1], ne[N << 1];
int depth[N], fa[N][K], w[N][K], p[N];
bool visited[N];
int n, m, idx;
struct Edge{
	int x, y, z;
	bool operator<(const Edge& others)const{
		return z > others.z;
	}
}e[M];
void add(int x, int y, int z){
	ver[idx] = y, edge[idx] = z, ne[idx] = head[x], head[x] = idx ++;
}
int Find(int x){
	return x == p[x]? x: p[x] = Find(p[x]);
}
void bfs(int root){
	queue<int>Q;
	Q.push(root);

	depth[root] = 1;
	visited[root] = true;
	while(!Q.empty()){
		int x = Q.front();
		Q.pop();
		for(int i = head[x]; i != -1; i = ne[i]){
			int y = ver[i], z = edge[i];
			
			if(visited[y]) continue;
			visited[y] = true;

			depth[y] = depth[x] + 1;			
			Q.push(y);
			fa[y][0] = x;
			w[y][0] = z;
			for(int k = 1; k < K; k ++){
				fa[y][k] = fa[fa[y][k - 1]][k - 1];
				w[y][k] = min(w[y][k - 1], w[fa[y][k - 1]][k - 1]);
			}			
		}
	}
}

int lca(int x, int y){
	if(Find(x) != Find(y)) return -1;

	int ans = 0x3f3f3f3f;
    if(depth[x] > depth[y]) swap(x, y);
    while(depth[y] > depth[x]){
    	ans = min(ans, w[y][int(log(depth[y] - depth[x])/log(2))]);
    	y = fa[y][int(log(depth[y] - depth[x])/log(2))];
    }
    if(x == y) return ans;
    for(int k = log(depth[x])/log(2); k >= 0; k --){

        if(fa[x][k] != fa[y][k]){
        	ans = min(ans, min(w[x][k], w[y][k]));
        	x = fa[x][k], y = fa[y][k];
        }
    }
    return min(ans, min(w[x][0], w[y][0]));
}

int main(){
	
	scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i ++){
		scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].z);
	}
	sort(e, e + m);
	
	memset(head, -1, sizeof(head));
	for(int i = 0; i < N; i ++) p[i] = i;
	for(int i = 0; i < m; i ++){
		int x = e[i].x, y = e[i].y, z = e[i].z;
		
		int root_x = Find(x), root_y = Find(y);
		if(root_x != root_y){
			
			p[root_x] = root_y;
			add(x, y, z), add(y, x, z);
		}
	}

	for(int i = 1; i <= n; i ++){
		if(!visited[i]) bfs(i);
	}
	
	int query, x, y;
	scanf("%d", &query);
	while(query --){
		scanf("%d%d", &x, &y);
		
		printf("%d\n", lca(x, y));

	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章