题目描述:

小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. UML-为什么要使用层?

    1.内聚职责:使关系分离.减少耦合和依赖,提高潜在复用性. 2.领域层和技术服务层可以是分布式的 3.利于团队开发

  2. PAT甲级——1061 Dating (20分)

    Sherlock Holmes received a note with some strange strings: Let's date! 3485djDkxh4hhGE 2984akDfkkkkg ...

  3. Go-简介-发展

    01-Go语言介绍 目录 Go语言介绍 Go语言特性 Go语言发展(版本/特性) Go语言应用 谁在用 应用领域 Go语言项目 Go语架构 Go语言发展前景 Go语言介绍 Go 即Golang,是Go ...

  4. memcached redis 本质区别是功能多少

    功能: 1.memcached 数据类型比较单一,数据淘汰策略单一,功能简单 2.redis 数据类型比较全面, 数据淘汰策略比较多,功能较强 有持久化能力,可以持久存储少量数据(数据量不会大于本机内 ...

  5. Activity组件(三):通过对象实现信息添加及展示

    在对组件进行注册时,只注册了EditText,却忘记了Button,导致程序一直闪退 输入信息 点击添加 成功跳转页面,并将数据传递 User.java package com.example.reg ...

  6. zabbix自定义添加主机

    1.安装zabbix-agent [root@web01 ~]# rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/3.4/rhe ...

  7. [Algo] 306. Check If Linked List Is Palindrome

    Given a linked list, check whether it is a palindrome. Examples: Input:   1 -> 2 -> 3 -> 2 ...

  8. Codeforces Round #573 (Div. 1) 差F

    Codeforces Round #573 (Div. 1) E 题意:二维平面上有 n 个点,你可以放至多 m 条直线使得 (0,0) 与每个点的连线至少与一条直线相交.求原点与所有直线的距离最小值 ...

  9. 达梦、oracel、mysql数据库兼容

    联合表更新sql语句: 只支持mysql.oracle,不支持达梦 update to_pub_report a, to_pub_rec_process b set a.Satisfy_ID , a. ...

  10. 八、linux-mysql的mysql主从复制原理和实战

    1.mysql主从复制介绍 mysql支持单向.双向.链式级联.实时.异步复制,在复制过程中,一台服务器充当主服务器(Master),而一个或多个其它服务器充当从服务器(Slave). 复制:单向同步 ...