• loj #137 and #6021


    最小瓶颈路 加强版
    重构树
    最小生成树在合并 (x, y) 时,新建节点 z,link(x, z), link(y, z), 新建节点的权值为 w_{x,y}, 这样的

    话任意两点的 answer 为新树上两点 lca 的权值,由于询问次数非常多,显然不可以 logn 求 lca。这里利用

    RMQ 求 lca,预处理后时间复杂度 O(1)

    #include <bits/stdc++.h>
    
    const int N = 7e4 + 10, M = 1e5 + 10, Mod = 1e9 + 7;
    
    int n, m;
    struct Node {
    	int u, v, w;
    	bool operator < (const Node a) const {return w < a.w;}
    } E[M];
    int A, B, C, P;
    
    inline int Rand() {A = (A * B + C) % P; return A;}
    
    int fa[N << 1];
    int Get(int x) {return x == fa[x] ? x : fa[x] = Get(fa[x]);}
    
    std:: vector <int> Vec[N << 1];
    int tot_point;
    int Val[N << 1];
    
    void Rebuild() {
    	tot_point = n;
    	for(int i = 1; i <= (n << 1); i ++) fa[i] = i;
    	for(int i = 1; i <= m && tot_point != n + n - 1; i ++) {
    		int fau = Get(E[i].u), fav = Get(E[i].v);
    		if(fau != fav) {
    			tot_point ++;
    			fa[fau] = fa[fav] = tot_point;
    			Vec[tot_point].push_back(fau);
    			Vec[tot_point].push_back(fav);
    			Val[tot_point] = E[i].w;
    		}
    	}
    }
    
    int deep[N << 1], In[N << 1], Id[N << 2];
    int Tr;
    
    void Dfs(int u, int dep) {
    	deep[u] = dep, In[u] = ++ Tr; Id[Tr] = u; 
    	int S = Vec[u].size();
    	for(int i = 0; i < S; i ++) Dfs(Vec[u][i], dep + 1), Id[++ Tr] = u;
    }
    
    int f[N << 2][30], Pow[30], Log[N << 2];
    
    #define T Tr
    void Make_st() {
    	for(int i = 0; (Pow[i] = (1 << i)) <= T; i ++);
    	Log[1] = 0;
    	for(int i = 2; i <= T; i ++) Log[i] = Log[i >> 1] + 1;
    	for(int i = 1; i <= T; i ++) f[i][0] = Id[i];
    	for(int i = 1; Pow[i] <= T; i ++)
    		for(int j = 1, ti = T - Pow[i] + 1; j <= ti; j ++)
    			f[j][i] = (deep[f[j][i - 1]] < deep[f[j + Pow[i - 1]][i - 1]] ? f[j][i - 
    
    1] : f[j + Pow[i - 1]][i - 1]);
    }
    
    int main() {
    	std:: cin >> n >> m;
    	for(int i = 1; i <= m; i ++) {
    		int u, v, w; std:: cin >> u >> v >> w;
    		E[i] = (Node) {u, v, w};
    	}
    	std:: sort(E + 1, E + m + 1);
    	Rebuild();
    	Dfs(tot_point, 1);
    	Make_st();
    	int Q; std:: cin >> Q;
    	std:: cin >> A >> B >> C >> P;
    	int Ans = 0;
    	for(; Q; Q --) {
    		int _1 = Rand() % n + 1, _2 = Rand() % n + 1;
    		int u = In[_1], v = In[_2];
    		if(u == v) continue;
    		if(u > v) std:: swap(u, v);
    		int t;
    		int ID = f[u][t = Log[v - u + 1]];
    		if(deep[ID] > deep[f[v - Pow[t] + 1][t]]) ID = f[v - Pow[t] + 1][t];
    		if((Ans += Val[ID]) >= Mod) Ans -= Mod;
    	}
    	std:: cout << Ans;
    	return 0;
    }
    
  • 相关阅读:
    我的学习思维:有关时间的管理
    Eureka的故事,专注能让你看到别人看不到的事情
    善用思维导图来整理发散的思维
    二八原理:人才招聘中的二八原理
    二八原理:员工激励中的二八原理
    二八原理:员工的三种类型
    二八原理:你必须知悉的二八原理
    Java程序员笔试、面试题目
    String StringBuffer StringBuilder
    log4j的使用详细解析
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9672626.html
Copyright © 2020-2023  润新知