首页 > 其他分享 >次小生成树

次小生成树

时间:2023-07-11 12:14:40浏览次数:32  
标签:dep ma fa int 生成 ++ qu

次小生成树

定义:边权之和大于最小生成树边权之和的生成树中最小的一个

思路:枚举所有未连接的边连上,那么一定会出现一个环,再去掉环上最大的边(如果与新加的边等大就要去次小边),这个最小值就为次小生成树的值

朴素求法:先用kruskal求出最小生成树,然后从每个点开始找到其他点的最大边与次大边,然后枚举所有边

复杂度\(O(n^2+m)\)

LAC优化:就是只讨论一棵树,对每个点记录向上跳\(2^i\)经过的最大边与次大边

注意LAC的i=0时的特殊处理

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
const int N = 1e5 + 10,M = 3e5 + 10;
int n,m,sum;

vector<PII> ed[N];//新图
struct edge{int u,v,len;
bool operator<(const edge &x)const{return len < x.len;}};
edge _ed[M];//旧图
int pre[N];//并查集
bool use[M];//边使用
void init(){for(int i = 1;i <= n;i++) pre[i] = i;}//并查集初始化
int find(int x){if(pre[x] == x) return pre[x];else return pre[x] = find(pre[x]);}
void kruskal(){
	init();
	sort(_ed + 1,_ed + 1 + m);
	for(int i = 1;i <= m;i++){
		if(find(_ed[i].u) != find(_ed[i].v)){
			use[i] = 1;
			sum += _ed[i].len;
			pre[find(_ed[i].u)] = find(_ed[i].v);
			ed[_ed[i].u].push_back({_ed[i].v,_ed[i].len});
			ed[_ed[i].v].push_back({_ed[i].u,_ed[i].len});
		}
	}
}

int dep[N],fa[N][21] = {0};
PII ma[N][21];
void bfs(){
	queue<int> qu;
	qu.push(1);
	dep[1] = 1;
	while(!qu.empty()){
		int u = qu.front();
		qu.pop();
		for(auto e:ed[u]){
			int v = e.fi,len = e.se;
			if(dep[v]) continue;
			qu.push(v);
			dep[v] = dep[u] + 1;
			fa[v][0] = u;
			ma[v][0].fi = len,ma[v][0].se = -1;
			for(int i = 1;i <= 20;i++){
				int faa = fa[v][i - 1];
				fa[v][i] = fa[faa][i - 1];
				ma[v][i].fi = max(ma[v][i-1].fi,ma[faa][i-1].fi);
				if(ma[v][i-1].fi == ma[faa][i-1].fi) ma[v][i].se = max(ma[v][i-1].se,ma[faa][i-1].se);
				else ma[v][i].se = min(ma[v][i-1].fi,ma[faa][i-1].fi);
			}
		}
	}
}

int d[N];
int lca(int x,int y,int w){
	int idx = 0;
	if(dep[x] < dep[y]) swap(x,y);//让x深度更深
	for(int i = 20;i >= 0;i--){//到同一深度
		if(dep[fa[x][i]] >= dep[y]){
			d[++idx] = ma[x][i].fi;
			d[++idx] = ma[x][i].se;
			x = fa[x][i];
		}
	}
	if(x != y){
		for(int i = 20;i >= 0;i--){
			if(fa[x][i] != fa[y][i] || i == 0){
				d[++idx] = ma[x][i].fi;
				d[++idx] = ma[x][i].se;
				d[++idx] = ma[y][i].fi;
				d[++idx] = ma[y][i].se;
				x = fa[x][i];
				y = fa[y][i];
				if(i == 0 && x != y)
				    i++;
			}
		}
	}
	int ma = -1;
	for(int i = 1;i <= idx;i++)
		if(d[i] != w && d[i] > ma) ma = d[i];
	if(ma == -1)
		return 1e18;
	return - ma + w;
}

signed main(){
	cin >> n >> m;
	for(int i = 1;i <= m;i++){
		int x,y,z;cin >> x >> y >> z;
		_ed[i] = {x,y,z};
	}
	kruskal();
	bfs();
	int ans = 1e18;
	for(int i = 1;i <= m;i++){
		if(use[i]) continue;
		ans = min(ans,sum + lca(_ed[i].u,_ed[i].v,_ed[i].len));
	}
	cout << ans << endl;
}

标签:dep,ma,fa,int,生成,++,qu
From: https://www.cnblogs.com/xxcdsg/p/17544277.html

相关文章

  • 最小生成树
    最小生成树定义边权和最小的生成树Kruskal算法让边从小到大排序,如果不在同一集合,就加入#include<bits/stdc++.h>usingnamespacestd;constintMAXN=5e3+10,MAXM=2e5+10;intn,m;inta[MAXN];intfind(intx){ if(a[x]==x)returnx; elsereturna[......
  • MATLAB代码:基于概率距离快速削减法的风光场景生成与
    MATLAB代码:基于概率距离快速削减法的风光场景生成与削减方法关键词:风光场景生成场景削减概率距离削减法蒙特卡洛法仿真平台:MATLAB平台优势:代码具有一定的深度和创新性,注释清晰,非烂大街的代码,非常精品!主要内容:代码主要做的是风电、光伏以及电价场景不确定性模拟,首先由一组确定性......
  • MATLAB代码:基于列约束生成法CCG的两阶段鲁棒问题求解
    MATLAB代码:基于列约束生成法CCG的两阶段鲁棒问题求解关键词:两阶段鲁棒列约束生成法CCG算法鲁棒优化参考文档:《Solvingtwo-stagerobustoptimizationproblemsusingacolumn-and-constraintgenerationmethod》仿真平台:MATLABYALMIP+CPLEX优势:代码注释详实,适合参考学习,非......
  • logstash+Elasticseach单节点 让logstash生成单副本索引
    要让Logstash和Elasticsearch生成单副本索引,请按照以下步骤更改Logstash的输出配置文件:打开Logstash配置文件,该文件默认位于 logstash/config 目录下。找到输出部分配置,并添加以下行:output{elasticsearch{hosts=>["localhost"]index=>"your......
  • 根据姓名生成邮箱号
    importrandomimportpypinyindefgen_mail(word):#根据姓名生成邮箱号s=''foriinpypinyin.pinyin(word,style=pypinyin.NORMAL):s+=''.join(i)r=''for_inrange(4):r+=str(random.randi......
  • 图的应用--最小生成树
    图的应用--最小生成树生成树概念:所有顶点均由边连接在一起.但不存在回路.一个图可以有许多不同的生成树.生成树特点:生成树的顶点个数与图的顶点个数相同.生成树是图的极小联通子图,去掉一条边则非联通一个有n个顶点的连通图的生成树有n-1条边在生成树中再加一条边必然......
  • 根据模板动态生成word(二)使用poi生成word
    @目录一、准备模板1、创建模板文件二、代码实践1、引入依赖2、自定义XWPFDocument2、公用的方法和变量3、工具类引用的包名4、段落文本替换5、图片替换6、表格替换7、完整的工具类代码三、验证模板生成1、测试代码2、生成效果四、总结一、准备模板1、创建模板文件创建一个word......
  • 考虑多风场出力相关性的可再生能源场景生成/风电场景生成,并通过聚类算法场景削减成几
    考虑多风场出力相关性的可再生能源场景生成/风电场景生成,并通过聚类算法场景削减成几个场景,每个场景都有确定的出现概率。完美复现《考虑多风电场出力Copula相关关系的场景生成方法》Copula函数(连接函数)描述空间相邻风电场间的相关性,提出一种基于Copula函数生成风电场出力......
  • MATLAB代码:基于列约束生成法CCG的两阶段问题求解 关键词:两阶
    MATLAB代码:基于列约束生成法CCG的两阶段问题求解关键词:两阶段鲁棒列约束生成法CCG算法参考文档:《Solvingtwo-stagerobustoptimizationproblemsusingacolumn-and-constraintgenerationmethod》仿真平台:MATLABYALMIP+CPLEX主要内容:代码构建了两阶段鲁棒优化模型,并用文......
  • SVPWM仿真和基于DSP28335的PIL(处理器在环) 仿真模型(将matlab仿真算法生成代码在DSP中
    SVPWM仿真和基于DSP28335的PIL(处理器在环)仿真模型(将matlab仿真算法生成代码在DSP中在线运行返回数据给Matlab)验证算法可行性和实时性。对于数字信号处理很有用。ID:73400638006173885......