• 洛谷 P4180


    题目链接:P4180 [BJWC2010]严格次小生成树

    题目大意

    就是求严格次小生成树, 即找到一个生成树, 使其子树和大于最小生成树,且最小

    solution

    那我们怎么求呢?

    我们先建出最小生成树肯定不亏,然后我们根据最小生成树的性质,每加入一条边会发现构成了一个环,然后呢我们在这个环中找到最大值和次大值,然后如果最大值和个加入的边不相等就删去最大值,加入这条边,反之删去最小值,加入这条边,然后最大值和最小值可以用倍增来维护

    Code:

    /**
    *    Author: Alieme
    *    Data: 2020.8.31
    *    Problem: P4180
    *    Time: O()
    */
    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    #define int long long
    #define rr register
    
    #define inf 1e15
    #define MAXN 300010
    
    using namespace std;
    
    inline int read() {
    	int s = 0, f = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    	return f ? -s : s;
    }
    
    void print(int x) {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) print(x / 10);
    	putchar(x % 10 + 48);
    }
    
    struct Ufs {
    	int fa[MAXN];
    	inline void clear(int x) {for (rr int i = 1; i <= x; i++) fa[i] = i;}
    	int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
    	inline void merge(int x, int y) {x = find(x), y = find(y); if (x != y) fa[x] = y;}
    	inline bool check(int x, int y) {return find(x) == find(y);}
    }S;
    
    struct Gragh {
    	int u, v, w;
    	Gragh() {}
    	Gragh(int U, int V, int W) {u = U, v = V, w = W;}
    	bool operator <(const Gragh &b) const {return w < b.w;}
    }g[MAXN];
    
    struct Edge {
    	int nxt;
    	int to;
    	int val;
    	Edge() {}
    	Edge(int Nxt, int To, int Val) {nxt = Nxt, to = To, val = Val;}
    }e[MAXN << 1];
    
    int n, m, tot, ans = inf, cnt;
    
    int head[MAXN << 1], dep[MAXN];
    
    int fa[MAXN][30], minn[MAXN][30], maxx[MAXN][30];
    
    bool vis[MAXN];
    
    inline void add(int from, int to, int val) {
    	e[++tot] = Edge(head[from], to, val);
    	head[from] = tot;
    }
    
    void dfs(int x, int fath) {
    	fa[x][0] = fath;
    	dep[x] = dep[fath] + 1;
    	for (rr int i = head[x]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if (to == fath) continue;
    		maxx[to][0] = e[i].val;
    		minn[to][0] = -inf;
    		dfs(to, x);
    	}
    }
    
    inline void init() {
    	minn[1][0] = inf;
    	dfs(1, 0);
    	for (rr int i = 1; i <= 18; i++)
    		for (rr int j = 1; j <= n; j++) {
    			fa[j][i] = fa[fa[j][i - 1]][i - 1];
    			maxx[j][i] = max(maxx[j][i - 1], maxx[fa[j][i - 1]][i - 1]);
    			minn[j][i] = min(minn[j][i - 1], minn[fa[j][i - 1]][i - 1]);
    			if (maxx[j][i - 1] > maxx[fa[j][i - 1]][i - 1]) minn[j][i] = max(minn[j][i], maxx[fa[j][i - 1]][i - 1]);
    			else if (maxx[j][i - 1] < maxx[fa[j][i - 1]][i - 1]) minn[j][i] = max(minn[j][i], maxx[j][i - 1]);
    		}
    }
    
    inline void kruskal() {
    	S.clear(n);
    	sort(g + 1, g + 1 + m);
    	for (rr int i = 1; i <= m; i++) {
    		int u = g[i].u, v = g[i].v, w = g[i].w;
    		if (S.check(u, v)) continue;
    		vis[i] = 1;
    		cnt += w;
    		S.merge(u, v);
    		add(u, v, w);
    		add(v, u, w);
    	}
    }
    
    inline int LCA(int x, int y) {
    	if (dep[x] < dep[y]) swap(x, y);
    	for (rr int i = 18; i >= 0; i--)
    		if (dep[fa[x][i]] >= dep[y])
    			x = fa[x][i];
    	if (x == y) return x;
    	for (rr int i = 18; i >= 0; i--) 
    		if (fa[x][i]^fa[y][i])
    			x = fa[x][i], y = fa[y][i];
    	return fa[x][0];
    }
    
    inline int query(int u, int v, int maxxx) {
    	int ans = -inf;
    	for (int i = 18; i >= 0; i--) 
    		if (dep[fa[u][i]] >= dep[v]) {
    			if (maxxx != maxx[u][i]) ans = max(ans, maxx[u][i]);
    			else ans = max(ans, minn[u][i]);
    			// cout << ans << " " << maxx[u][i] << " " << minn[u][i] << "
    "; 
    			u = fa[u][i];
    		}
    	return ans;
    }
    
    signed main() {
    	n = read();
    	m = read();
    	for (rr int i = 1; i <= m; i++) g[i].u = read(), g[i].v = read(), g[i].w = read();
    	kruskal();
    	init();
    	for (rr int i = 1; i <= m; i++) 
    		if (!vis[i]) {
    			int u = g[i].u, v = g[i].v, w = g[i].w;
    			int lca = LCA(u, v);
    			int maxu = query(u, lca, w);
    			int maxv = query(v, lca, w);
    			ans = min(ans, cnt - max(maxu, maxv) + w);
    		}
    	print(ans);
    }
    
  • 相关阅读:
    Javascript中对文字编码的三个函数
    Web.config文件中关于Cookie安全性的考量和设置
    面试时被问到的问题
    JQuery中查找父元素,子元素,追加元素,插入元素和删除元素 及其他常用方法
    JQuery插件开发学习
    Umbraco image中使用Crop URL
    SQL中的row_number() over()解释
    GEO,IGSO,MEO,LEO
    计算机网络端口常识
    VMnet1和VMnet8 未识别的网络的解决方法
  • 原文地址:https://www.cnblogs.com/lieberdq/p/13594090.html
Copyright © 2020-2023  润新知