算法笔记--次小生成树 && 次短路 && k 短路
1.次小生成树
非严格次小生成树:边权和小于等于最小生成树的边权和
严格次小生成树: 边权和小于最小生成树的边权和
算法:先建好最小生成树,然后对于每条不在最小生成树上的边(u,v,w)如果我们把它放到最小生成树中,会形成一个环,那么再从这个环上删除一个除加进去的边外且小于(或等于)当前w的最大权值边,可以用倍增(或树剖)维护链上的最大值来实现非严格的,对于严格的来说,最大值可能等于w,那么就再维护一个次大值。
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e5 + , M = 3e5 + ;
const int INF = 0x3f3f3f3f;
pair<int, pii> e[M];
vector<pii> g[N];
int fa[N], deep[N], anc[N][];
pii mx[N][];
bool vis[M];
void init(int n) {
for (int i = ; i <= n; ++i) fa[i] = i;
}
int Find(int x) {
if(x == fa[x]) return x;
else return fa[x] = Find(fa[x]);
}
pii MX(pii a, pii b) {
pii res = {-INF, -INF};
if(a.fi > b.fi) res.fi = a.fi, res.se = b.fi;
else if(a.fi < b.fi) res.fi = b.fi, res.se = a.fi;
else res.fi = a.fi;
res.se = max(res.se, a.se);
res.se = max(res.se, b.se);
return res;
}
void dfs(int u, int o, int w) {
deep[u] = deep[o] + ;
if(u != ) {
anc[u][] = o;
for (int i = ; i < ; ++i) anc[u][i] = anc[anc[u][i-]][i-];
mx[u][] = {w, -INF};
for (int i = ; i < ; ++i) mx[u][i] = MX(mx[u][i-], mx[anc[u][i-]][i-]);
}
else {
for (int i = ; i < ; ++i) anc[u][i] = o;
for (int i = ; i < ; ++i) mx[o][i] = mx[u][i] = {-INF, -INF};
}
for (pii p : g[u]) {
int v = p.fi;
int w = p.se;
if(v != o) {
dfs(v, u, w);
}
}
}
int lca(int u, int v) {
if(deep[u] < deep[v]) swap(u, v);
for (int i = ; i >= ; --i) if(deep[anc[u][i]] >= deep[v]) u = anc[u][i];
if(u == v) return u;
for (int i = ; i >= ; --i) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
return anc[u][];
}
int main() {
int n, m;
LL tot = ;
scanf("%d %d", &n, &m);
for (int i = ; i <= m; ++i) scanf("%d %d %d", &e[i].se.fi, &e[i].se.se, &e[i].fi);
init(n);
sort(e+, e++m);
for (int i = ; i <= m; ++i) {
int x = Find(e[i].se.fi);
int y = Find(e[i].se.se);
if(x == y) vis[i] = true;
else fa[x] = y, g[e[i].se.fi].pb({e[i].se.se, e[i].fi}), g[e[i].se.se].pb({e[i].se.fi, e[i].fi}), tot += e[i].fi;
}
dfs(, , );
LL ans = LONG_MAX;
for (int i = ; i <= m; ++i) {
if(vis[i]) {
int u = e[i].se.fi;
int v = e[i].se.se;
int l = lca(u, v);
pii mm = {-INF, -INF};
for (int i = ; i >= ; i--) if(deep[anc[u][i]] >= deep[l]) mm = MX(mm, mx[u][i]), u = anc[u][i];
;
for (int i = ; i >= ; i--) if(deep[anc[v][i]] >= deep[l]) mm = MX(mm, mx[v][i]), v = anc[v][i] ;
if(mm.fi < e[i].fi) ans = min(ans, e[i].fi + tot - mm.fi);
else if(mm.se < e[i].fi && mm.se != -INF)ans = min(ans, e[i].fi + tot - mm.se);
}
}
printf("%lld\n", ans);
return ;
}
2.次短路
次短路:到某个点的距离比最短路距离大的距离
参照挑战程序设计竞赛P108
到某个点v的次短路要么是其他某个顶点u的最短路再加上u -> v的边,要么是到u的次短路再加上u -> v的边,于是考虑Dijkstra算法更新最短路和次短路。
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 5e3 + ;
vector<pii> g[N];
int d[N], dd[N];
priority_queue<pii, vector<pii>, greater<pii> > q;
int main() {
int n, m, u, v, w;
scanf("%d %d", &n, &m);
for (int i = ; i <= m; ++i) {
scanf("%d %d %d", &u, &v, &w);
g[u].pb({v, w});
g[v].pb({u, w});
}
mem(d, 0x7f);
mem(dd, 0x7f);
d[] = ; //dd[1]不能等于0,n=1且自环的情况
q.push({, });
while(!q.empty()) {
pii p = q.top();
q.pop();
int u = p.se;
if(dd[u] < p.fi) continue;
for (int i = ; i < g[u].size(); ++i) {
int v = g[u][i].fi;
int w = g[u][i].se;
int d1 = p.fi + w;
if(d1 < d[v]) {
swap(d1, d[v]);
q.push({d[v], v});
}
if(d1 < dd[v] && d1 > d[v]) {
dd[v] = d1;
q.push({dd[v], v});
}
}
}
printf("%d\n", dd[n]);
return ;
}
ps:最短路记数也可以用Dijkstra,考虑松弛时如果d[v] > d[u] + w, 那么cnt[v] = cnt[u], 如果d[v] == d[u] + w, 那么cnt[v] += cnt[u]。
3.k短路
A* 或者 可持久化堆
都不会,未完待续。。。
算法笔记--次小生成树 && 次短路 && k 短路的更多相关文章
- 最短路 次短路 k短路(k很小)
最短路 luogu 3371 https://www.luogu.org/problemnew/show/P3371 #include <cstdio> #include <cstd ...
- BZOJ1726: [Usaco2006 Nov]Roadblocks第二短路 K短路
Description 贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友.贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样, ...
- 疯子的算法总结10--最小生成树Kruscal
按照权值排序可得,就有如下顺序: 1. 1-2 1 2. 1-4 2 3. 1-5 2 4. 2-5 3 5. 2-3 4 6. 4-5 4 每次选取最小边泉,判断是否同属一个集合,如果不属于同一集合 ...
- 算法笔记_079:蓝桥杯练习 区间k大数查询(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表 ...
- 次小生成树题(k) poj1679The Unique MST
http://poj.org/problem?id=1679 #include<iostream> #include<vector> #include<cstdio> ...
- URAL 1416 Confidential (最小生成树+次小生成树)
Description Zaphod Beeblebrox - President of the Imperial Galactic Government. And by chance he is a ...
- 沈阳网络赛D-Made In Heaven【k短路】【模板】
One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with her. However, Pucci ...
- luogu 2483 K短路 (可持久化左偏树)
题面: 题目大意:给你一张有向图,求1到n的第k短路 $K$短路模板题 假设整个图的边集为$G$ 首先建出以点$n$为根的,沿反向边跑的最短路树,设这些边构成了边集$T$ 那么每个点沿着树边走到点$n ...
- 算法笔记_075:蓝桥杯练习 最短路(Java)
目录 1 问题描述 2 解决方案 2.1 floyd算法解决 2.2 spfa算法解决 1 问题描述 问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从 ...
随机推荐
- 解决页面使用ifrmae后,在session失效后登录页面在子页面中显示(子窗体出现父窗体)
在登录页面中添加js判断当前页面是否是父页面,诺不是则父页面跳转至登录页面. <script type="text/javascript"> //解决登录后多个父窗体问 ...
- flask下载文件---文件流
html: <a name="downloadbtn" class="btn btn-success pull-right" href="/do ...
- Qt QLabel QTextBrowser 实现网址链接
勾选属性: 并且编辑网址链接: QLabel--点击text属性的...: QTextBrowser--双击控件
- Python学习笔记(Ⅱ)——循环/选择/函数
一.循环结构 python中提供了for循环和while循环两种操作,没有do……while语句. 1.for循环: 与其他语言中for循环的常见的写法如for (int i=0;i<10;i+ ...
- Rsync+unison双向文件同步
1.配置RSYNC服务器的同步源: 基于SSH同步源 rsync -avz /server/rsyncd/* chen@172.16.23.204:/client/rsyncd 基于RSYNC同步源 ...
- CentOS 7 配置DHCP中继代理服务
DHCP服务器只作用于局域网同一网段内,客户端是通过广播消息来获得DHCP服务器响应后才能得到IP地址的,但广播消息不能跨越子网,那么如何让客户端获取到DHCP服务器提供的IP地址呢?这就是DHCP中 ...
- Windows下的Python安装与环境变量的配置
Windows下的Python安装与环境变量的配置 第一步:python下载: Python安装包下载地址:http://www.python.org/ 第二步:python安装: 双击下载包,进入P ...
- 福州大学软件工程1916|W班 第5次作业成绩排名
1. 作业链接: https://edu.cnblogs.com/campus/fzu/SoftwareEngineering1916W/homework/2768 2. 评分准则: 本次作业评分分为 ...
- 微信网页授权获取用户openid及用户信息
$code = $_GET["code"];//获取code $appid=“xxxx”;//公众号appid $APPSECRET="xxx";//公众号ap ...
- 网络-02-端口号-linux端口详解大全
端口详解 1 tcpmux TCP Port Service Multiplexer 传输控制协议端口服务多路开关选择器 2 compressnet Management Utility compr ...