• 严格最小生成树


    原理简介

    非严格次小生成树是在最小生成树有多棵时未被选为最小生成树的树,而严格最小生成树要求其边权和是第一个大于最小生成树的边权和。两者算法大致相同,都是枚举非树边加入树中,很明显会形成一棵基环树,在基环的环(不包含加入的边)中找出最大值被加入边代替更新答案,只是单纯找最大得到非严格,而找出第一个严格小于加入边权值的边得到的是严格次小生成树(被相同权值的边替换边权和不会变大哦~~~)。

    例题Luogu-P4180

    模板题

    #include <iostream> 
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <cstring>
    #include <algorithm>  
    #define ll long long
    #define rint register int
    #define mid ((L + R) >> 1)
    #define lson (x << 1)
    #define rson (x << 1 | 1)
    using namespace std;
    template<typename xxx>inline void read(xxx &x) {
    	int f = 1;char c = getchar();x = 0;
    	for(;c ^ '-' && !isdigit(c);c = getchar());
    	if(c == '-') f = -1,c = getchar();
    	for(;isdigit(c);c = getchar()) x = (x<<3) + (x<<1) + (c ^ '0');
    	x *= f;
    } 
    template<typename xxx>inline void print(xxx x) {
    	if(x < 0) {
    		putchar('-');
    		x = -x;
    	}
    	if(x > 9) print(x / 10);
    	putchar(x % 10 + '0');
    }
    const int maxn = 1000010;
    const int mod = 998244353;
    const int inf = 0x7fffffff;
    struct node{
    	int a,b;ll c;
    }g[maxn];
    inline bool gmp(node x,node y) {
    	return x.c < y.c;
    }
    struct edge {
    	int to,last;
    	ll val;
    }e[maxn<<1];
    int head[maxn],tot;
    inline void add(int from,int to,ll val) { 
    	++tot;
    	e[tot].to = to;
    	e[tot].val = val;
    	e[tot].last = head[from];
    	head[from] = tot;
    } 
    int n,m,s;
    int w[maxn],cnt;
    int dad[maxn];
    int dep[maxn];
    int rev[maxn];
    int seg[maxn];
    int siz[maxn];
    int son[maxn];
    int top[maxn];
    inline void ddfs1(int x,int da) {
    	siz[x] = 1;dad[x] = da;
    	dep[x] = dep[da] + 1;
    	for(rint i = head[x];i;i = e[i].last) {
    		if(e[i].to == da) continue;
    		ddfs1(e[i].to,x);
    		siz[x] += siz[e[i].to];
    		if(son[x] == 0 || siz[son[x]] < siz[e[i].to]) son[x] = e[i].to; 
    	}
    	return ;
    }
    inline void ddfs2(int x,int tp) {
    	seg[x] = ++cnt;
    	rev[cnt] = x;
    	top[x] = tp;
    	if(!son[x]) return ;
    	ddfs2(son[x],tp);
    	for(rint i = head[x];i;i = e[i].last) {
    		if(e[i].to == dad[x] || e[i].to == son[x]) continue;
    		ddfs2(e[i].to,e[i].to);
    	}
    	return ;
    }
    ll sum,mks[maxn<<2],sec[maxn<<2];
    inline void pushup(int x) {
    	mks[x] = max(mks[lson],mks[rson]);
    	if(mks[lson] == mks[rson]) sec[x] = max(sec[lson],sec[rson]);
    	else sec[x] = min(mks[lson],mks[rson]);
    	return ;
    }
    inline void update(int x,int L,int R,int pos,ll val) {
    	if(L == R) {
    		mks[x] = val;
    		sec[x] = -1e17;
    		return;
    	} 
    	if(pos <= mid) update(lson,L,mid,pos,val);
    	else update(rson,mid + 1,R,pos,val);
    	pushup(x);
    	return ;
    }
    inline ll qmax(int x,int L,int R,int l,int r,ll val) {
    	if(l <= L && R <= r) {
    		if(val == mks[x]) return sec[x];
    		else return mks[x];
    	}
    	ll ans = 0;
    	if(l <= mid) ans = max(ans,qmax(lson,L,mid,l,r,val));
    	if(r >  mid) ans = max(ans,qmax(rson,mid + 1,R,l,r,val));
    	return ans;
    }
    inline ll q1(int x,int y,ll val) {
    	ll ans = 0;
    	while(top[x] ^ top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x,y);
    		ans = max(ans,qmax(1,1,n,seg[top[x]],seg[x],val));
    		x = dad[top[x]];
    	}
    	if(x ^ y) {
    		if(dep[x] > dep[y]) swap(x,y);
    		ans = max(ans,qmax(1,1,n,seg[son[x]],seg[y],val));
    	} 
    	return ans;
    }
    int fa[maxn];
    inline int f(int x) {
    	while(x ^ fa[x]) x = fa[x] = fa[fa[x]];
    	return x;
    }
    int vis[maxn];
    int main() {
    	ll cnm = 1e17;
    	read(n);read(m);
    	for(rint i = 1;i <= n; ++i) fa[i] = i; 
    	for(rint i = 1;i <= m; ++i) {
    		read(g[i].a);
    		read(g[i].b);
    		read(g[i].c);
    	}
    	stable_sort(g + 1,g + m + 1,gmp); 
    	for(rint i = 1;i <= m; ++i) {
    		int x = f(g[i].a);
    		int y = f(g[i].b);
    		if(x ^ y) {
    			fa[x] = y;sum += g[i].c;
    			add(g[i].a,g[i].b,g[i].c);
    			add(g[i].b,g[i].a,g[i].c);
    		} else {
    			vis[i] = 1;
    		}
    	}
    	ddfs1(1,0);
    	ddfs2(1,1);
    	for(rint i = 1;i <= m; ++i) {
    		if(!vis[i]) {
    			if(dep[g[i].a] > dep[g[i].b]) {
    				update(1,1,n,seg[g[i].a],g[i].c);
    			} else {
    				update(1,1,n,seg[g[i].b],g[i].c);
    			}
    		}
    	}
    	for(rint i = 1;i <= m; ++i) {
    		if(vis[i]) {
    			ll fk = q1(g[i].a,g[i].b,g[i].c);
    			ll tem = sum - fk + g[i].c;
    			if(tem ^ sum && tem < cnm) cnm = tem;
    //			cout<<tem<<" "<<sum<<" "<<fk<<endl;
    		}
    	}
    	print(cnm);
    	return 0;
    }
    /*
    
    */
    
  • 相关阅读:
    Linux mysql忘记密码 修改密码 解决方法
    nginx http转https后js,css样式丢失/没显示
    Spring cron 表达式
    Python 学习笔记 -- 装饰器
    Python 学习笔记 -- 一些常用的BIF
    Python 学习笔记 -- 类的一些小知识
    Python 学习笔记 -- 继承与多态(入门级实例)
    Python 基础实战 -- 小游戏之乌龟吃鱼(其实只能看不能玩.....)
    Python 学习笔记 -- 类的访问限制
    Python 学习笔记 -- 类和实例
  • 原文地址:https://www.cnblogs.com/Thomastine/p/11832316.html
Copyright © 2020-2023  润新知