题目描述:

小C最近学了很多最小生成树的算法,Prim算法、Kurskal算法、消圈算法等等。正当小C洋洋得意之时,小P又来泼小C冷水了。小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是$E_M$,严格次小生成树选择的边集是$E_S$,那么需要满足:($value(e)$表示边e的权值)

这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

输入输出格式:

输入格式:

第一行包含两个整数N和M,表示无向图的点数与边数。接下来M行,每行3个数 x y z 表示,点x和点y之间有一条边,边的权值为z。

输出格式:

包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

输入输出样例:

输入样例:

1
2
3
4
5
6
7
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6

输出样例:

1
11

说明:

数据中无向图无自环
50%的数据$N≤2000,;M≤3000$
80%的数据$N≤50000,;M≤100000$
100%的数据$N≤100000,;M≤300000$, 边权值非负且不超过$10^9$。

SOL:

首先求出最小生成树,然后将最小生成树的边依次断开,换成指定的一条边,
求出这个环中最长的一条边,换掉即可。

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include<bits/stdc++.h>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define for_edge(i, x) for(RG int i=head[x];i;i=e[i].next)
#define clear(x, y) memset(x, y, sizeof(x));
using namespace std; template<typename T>
inline T read()
{
T data=0, w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1, ch=getchar();
while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+(ch^48), ch=getchar();
return data*w;
} const int maxn(100010), maxm(300010);
struct edge
{
int next, to;
long long dis;
} e[maxn << 1];
int head[maxn], e_num;
inline void add_edge(int from, int to, long long dis)
{
e[++e_num]={head[from], to, dis};
head[from]=e_num;
} struct edge_k { int from, to; long long dis; } edg[maxm];
inline bool cmp(const edge_k &a, const edge_k &b) { return a.dis<b.dis; }
int fa[ma 大专栏  洛谷P4180【Beijing2010组队】次小生成树Treexn], n, m;
long long value; bool use[maxm];
inline int find(const int &x) { return fa[x] == x ? x : fa[x]=find(fa[x]); }
inline void mst()
{
long long ans=0;
for(RG int i=1;i<=n;i++) fa[i]=i;
for(RG int i=1;i<=m;i++)
{
int x=find(edg[i].from), y=find(edg[i].to);
if(x!=y)
{
fa[max(x, y)]=min(x, y);
ans+=edg[i].dis;
use[i]=true;
add_edge(edg[i].from, edg[i].to, edg[i].dis);
add_edge(edg[i].to, edg[i].from, edg[i].dis);
}
}
value = ans;
} long long fst[maxn][18], sec[maxn][18], ANS=0;
int f[maxn][18], deep[maxn];
inline void dfs(int x)
{
for_edge(i, x)
{
int to=e[i].to; long long ds=e[i].dis;
if(to==f[x][0]) continue;
f[to][0]=x; fst[to][0]=sec[to][0]=ds;
deep[to]=deep[x]+1;
dfs(to);
}
}
inline void get_sec(long long &sec, long long a,
long long b, long long c,
long long d, long long _max)
{
if(a<_max) sec=a;
if(b<_max) sec=max(sec, b);
if(c<_max) sec=max(sec, c);
if(d<_max) sec=max(sec, d);
}
inline void init()
{
dfs(1);
for(RG int j=1;j<18;j++)
for(RG int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
long long f1=fst[i][j-1],
f2=fst[f[i][j-1]][j-1],
s1=sec[i][j-1],
s2=sec[f[i][j-1]][j-1];
fst[i][j]=max(f1, f2);
get_sec(sec[i][j], f1, f2, s1, s2, fst[i][j]);
}
} inline long long query(int a, int b, long long dis)
{
if(deep[a]<deep[b]) swap(a, b);
long long fsa=-1, sca=-1, fsb=-1, scb=-1;
int d=deep[a]-deep[b];
for(RG int i=0;(1<<i)<=d;i++)
{
if((1<<i)&d)
{
long long tmp=sca;
get_sec(sca, fsa, fst[a][i], tmp, sec[a][i], max(fsa, fst[a][i]));
fsa=max(fsa, fst[a][i]);
a=f[a][i];
}
}
if(a==b)
{
long long tmp=sca;
get_sec(sca, fsa, fsb, tmp, scb, max(fsa, fsb));
if(dis==max(fsa, fsb)) return value-sca+dis;
else return value-max(fsa, fsb)+dis;
}
for(RG int i=17;~i;i--)
{
if(f[a][i]!=f[b][i])
{
long long tmp=sca;
get_sec(sca, fsa, fst[a][i], tmp, sec[a][i], max(fsa, fst[a][i]));
fsa=max(fsa, fst[a][i]);
a=f[a][i];
tmp=scb;
get_sec(scb, fsb, fst[b][i], tmp, sec[b][i], max(fsb, fst[b][i]));
fsb=max(fsb, fst[b][i]);
b=f[b][i];
}
}
long long tmp=sca;
get_sec(sca, fsa, fst[a][0], tmp, sec[a][0], max(fsa, fst[a][0]));
fsa=max(fsa, fst[a][0]);
a=f[a][0];
tmp=scb;
get_sec(scb, fsb, fst[b][0], tmp, sec[b][0], max(fsb, fst[b][0]));
fsb=max(fsb, fst[b][0]);
b=f[b][0];
tmp=sca;
get_sec(sca, fsa, fsb, tmp, scb, max(fsa, fsb));
if(dis==max(fsa, fsb)) return value-sca+dis;
else return value-max(fsa, fsb)+dis;
} const long long I(9223372036854775807ll);
int main()
{
n=read<int>(); m=read<int>();
for(RG int i=1;i<=m;i++) edg[i].from=read<int>(), edg[i].to=read<int>(), edg[i].dis=read<long long>();
sort(edg+1, edg+m+1, cmp);
mst(); init();
ANS=I;
for(RG int i=1;i<=m;i++) if(!use[i]) ANS=min(ANS, query(edg[i].from, edg[i].to, edg[i].dis));
printf("%lldn", ANS);
return 0;
}

洛谷P4180【Beijing2010组队】次小生成树Tree的更多相关文章

  1. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  2. 洛谷P4180 [Beijing2010组队]次小生成树Tree

    题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...

  3. BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )

    做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...

  4. 1977: [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...

  5. 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增

    [BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...

  6. [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 5168  Solved: 1668[S ...

  7. 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)

    洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...

  8. 【洛谷P4180】严格次小生成树

    题目大意:给定一个 N 个顶点,M 条边的带权无向图,求该无向图的一个严格次小生成树. 引理:有至少一个严格次小生成树,和最小生成树之间只有一条边的差异. 题解: 通过引理可以想到一个暴力,即:先求出 ...

  9. 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree

    Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...

  10. (luogu4180) [Beijing2010组队]次小生成树Tree

    严格次小生成树 首先看看如果不严格我们怎么办. 非严格次小生成树怎么做 由此,我们发现一个结论,求非严格次小生成树,只需要先用kruskal算法求得最小生成树,然后暴力枚举非树边,替换路径最大边即可. ...

随机推荐

  1. echars 柱状图点击事件

     drawlineCRK() {       let _this = this;       ///绘制echarts 柱状图       let mycharts = this.$echarts.i ...

  2. 以KNN为例用sklearn进行数据分析和预测

    准备 相关的库 相关的库包括: numpy pandas sklearn 带入代码如下: import pandas as pd import numpy as np from sklearn.nei ...

  3. Python—构造单向链表数据类型

    # _*_ coding=utf-8 _*_ class Node: """ 创建链表的属性 """ def __init__(self, ...

  4. matlab代码学习_2018-7-28

    1.核范数||A|| * 是指矩阵奇异值的和,英文称呼叫Nuclear Norm.matlab code:[s, u, v] = svd(A); nulear_norm = sum(diag(s)); ...

  5. Matlab高级教程_第一篇:Matlab基础知识提炼_05

    第九节:矩阵的操作 第十节:数组与矩阵 linspace函数

  6. python常见内置函数总结

    简单的内置函数 len    求长度 min   求最小值 max  求最大值 sorted  排序 reversed   反向 sum   求和 进制转换 bin   转为二进制 oct   转为八 ...

  7. NAIPC2018

    NAIPC2018 参考:http://www.cnblogs.com/LQLlulu/p/9513669.html?tdsourcetag=s_pctim_aiomsg https://www.cn ...

  8. Matlab高级教程_第二篇:Matlab相见恨晚的模块_02_并行运算-2

    1 MATLAB并行计算-从个人桌面到远程集群和云(陈伟/魏奋)视频摘录笔记 https://cn.mathworks.com/videos/parallel-computing-with-matla ...

  9. JDBC常用驱动和语法汇总

    A. Firebird url=jdbc:firebirdsql:[HOST_NAME]/[PORT:][FULL_PATH_TO_DATABASE_FILE] driver=org.firebird ...

  10. 27)PHP,视图

    其实,视图就是一堆select形成的一个表格,但是这个表格也是存在一个数据库里面的,但是,他不会和一般的表格似得在数据库中显示,就好像虚拟存储器的那种感觉一样. 比如  必看我的一下句子 create ...