【Beijing 2010】 次小生成树
【题目链接】
【算法】
首先,有一个结论 : 一定有一棵严格次小生成树是在最小生成树的基础上去掉一条边,再加上一条边
这个结论的正确性是显然的
我们先用kruskal算法求出最小生成树,然后,枚举不在最小生成树上的边,我们发现若加上这条边,
则形成了一个环,用最小生成树的权值和加上这条边的权值再减去在这个环上且在最小生成树上权值
最大的边即为包括这条边的最小生成树的权值和
那么,树上倍增可以解决这个问题
因为是要求严格最小,所以我们不仅要记录最大值,还要记录次大值
时间复杂度 : O((N+M)log(N))
【代码】
注意使用long long,INF开到10^18!
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define MAXM 300010
#define MAXLOG 20
const long long INF = 1e18; struct info
{
int x,y;
long long w;
} edge[MAXM];
struct Edge
{
int to;
long long w;
int nxt;
} e[MAXM<<]; int i,n,m,tot;
int fa[MAXN],head[MAXN],dep[MAXN],anc[MAXN][MAXLOG];
long long ans = INF,val;
long long mx[MAXN][MAXLOG],nx[MAXN][MAXLOG];
bool on_mst[MAXM]; inline bool cmp(info a,info b) { return a.w < b.w; }
inline int get_root(int x)
{
if (fa[x] == x) return x;
return fa[x] = get_root(fa[x]);
}
inline void add(int x,int y,int w)
{
tot++;
e[tot] = (Edge){y,w,head[x]};
head[x] = tot;
}
inline void kruskal()
{
int i,sx,sy;
long long x,y,w;
for (i = ; i <= n; i++) fa[i] = i;
for (i = ; i <= m; i++) on_mst[i] = false;
sort(edge+,edge+m+,cmp);
for (i = ; i <= m; i++)
{
x = edge[i].x;
y = edge[i].y;
w = edge[i].w;
sx = get_root(x);
sy = get_root(y);
if (sx != sy)
{
val += w;
fa[sx] = sy;
on_mst[i] = true;
add(x,y,w);
add(y,x,w);
}
}
}
inline void dfs_init(int u)
{
int i,v;
for (i = ; i < MAXLOG; i++)
{
if (dep[u] < ( << i)) break;
anc[u][i] = anc[anc[u][i-]][i-];
mx[u][i] = max(mx[u][i-],mx[anc[u][i-]][i-]);
if (mx[u][i-] == mx[anc[u][i-]][i-]) nx[u][i] = max(nx[u][i-],nx[anc[u][i-]][i-]);
else nx[u][i] = max(min(mx[u][i-],mx[anc[u][i-]][i-]),max(nx[u][i-],nx[anc[u][i-]][i-]));
}
for (i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
if (anc[u][] != v)
{
dep[v] = dep[u] + ;
anc[v][] = u;
mx[v][] = e[i].w;
dfs_init(v);
}
}
}
inline long long get(int x,int y,long long w)
{
int i,t;
long long ret = ;
if (dep[x] > dep[y]) swap(x,y);
t = dep[y] - dep[x];
for (i = ; i < MAXLOG; i++)
{
if (t & ( << i))
{
if (mx[y][i] == w) ret = max(ret,nx[y][i]);
else ret = max(ret,mx[y][i]);
y = anc[y][i];
}
}
if (x == y) return ret;
for (i = MAXLOG - ; i >= ; i--)
{
if (anc[x][i] != anc[y][i])
{
if (mx[x][i] == w) ret = max(ret,nx[x][i]);
else ret = max(ret,mx[x][i]);
if (mx[y][i] == w) ret = max(ret,nx[y][i]);
else ret = max(ret,mx[y][i]);
x = anc[x][i];
y = anc[y][i];
}
}
if (mx[x][] != w) ret = max(ret,mx[x][]);
if (mx[y][] != w) ret = max(ret,mx[y][]);
return ret;
}
int main()
{ scanf("%d%d",&n,&m);
for (i = ; i <= m; i++) scanf("%lld%lld%lld",&edge[i].x,&edge[i].y,&edge[i].w);
kruskal();
dfs_init();
for (i = ; i <= m; i++)
{
if (!on_mst[i])
ans = min(ans,val+edge[i].w-get(edge[i].x,edge[i].y,edge[i].w));
}
printf("%lld\n",ans); return ;
}
【Beijing 2010】 次小生成树的更多相关文章
- [BJOI 2010]次小生成树Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- [Luogu P4180][BJWC 2010]严格次小生成树
严格次小生成树,关键是“严格”,如果是不严格的其实只需要枚举每条不在最小生成树的边,如果得到边权和大于等于最小生成树的结束就行.原理就是因为Kruskal非常贪心,只要随便改一条边就能得到一个非严格的 ...
- 次小生成树(lca)
题目描述 原题来自:BeiJing 2010 组队赛 给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树. 设最小生成树的边权之和为 sum,严格次小生成树就是指边权之和大于 sum 的生 ...
- hdu 4081 Qin Shi Huang's National Road System (次小生成树)
Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- HDU4081 Qin Shi Huang's National Road System —— 次小生成树变形
题目链接:https://vjudge.net/problem/HDU-4081 Qin Shi Huang's National Road System Time Limit: 2000/1000 ...
- HDU-4081.Qinshihuang'sNationalRoadSystem(次小生成树变种)
Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- HDU 4081Qin Shi Huang's National Road System(次小生成树)
题目大意: 有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点.秦始皇希望这所有n-1条路长度之和最短.然后徐福突然有冒出来,说是他有魔法,可以不用人力.财力就变 ...
- POJ1679 The Unique MST[次小生成树]
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 28673 Accepted: 10239 ...
- The Unique MST(次小生成树)
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22335 Accepted: 7922 Description Give ...
随机推荐
- 全国高校json数据包(复python解析代码)
由于这段时间需要有关学校的三级联动插件,找了很久没有找到合适的,所以去教育部官网下载了一份全国普通高校名单(2019年), 这里附上解析该xls文件的代码 import xlrd import jso ...
- Session与Token的区别
1. 为什么要有session的出现?答:是由于网络中http协议造成的,因为http本身是无状态协议,这样,无法确定你的本次请求和上次请求是不是你发送的.如果要进行类似论坛登陆相关的操作,就实现不了 ...
- C语言学习<输入输出函数,函数的调用>
#include <stdio.h> /* 输入输出函数的学习 函数的调用 2017.05.25 soulsjie */ //输入连个数字求最大值 void main(){ int Max ...
- add favorite & 收藏夹
add favorite // 收藏夹 function favorite (){ var ctrl = (navigator.userAgent.toLowerCase()).indexOf(&qu ...
- [HAOI2011]Problem b 题解
题目大意: 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y)=k. 思路: 设f(k)为当1≤x≤n,1≤y≤m,且n≤m,使gcd(x,y)=k的数对 ...
- [luoguP1058] 立体图(超级大模拟(¬︿̫̿¬☆))
传送门 看到题后整个人成了mengbier 但是仔细分析一下就很简单了,先确定好输出的图的长和宽. 然后从输入的矩形的左上角的最下面的开始填充,顺序是从下到上,从左到右,从后往前. 填充的时候直接覆盖 ...
- 前端开发:JavaScript---DOM & BOM
DOM:Document Object Model 文档对象类型 模态框案例 <!DOCTYPE html> <html lang="en"> <h ...
- android开发里跳过的坑——android studio 错误Error:Execution failed for task ':processDebugManifest'. > Manifest merger failed with multiple errors, see logs
使用AS在gradle里配置了多个定制版本,发现在编译版本切换时,会出现错误: Error:Execution failed for task ':processDebugManifest'.> ...
- 【small项目】MySQL第二天早上第一次连接超时报错,解决方法com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
MySQL第二天早上第一次连接超时报错,解决方法com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link ...
- msp430入门编程05
msp430中C语言的运算符和表达式 msp430中C语言的程序结构06 msp430中C语言的函数及实现07 msp430中C语言操作端口I/O10 msp430中C语言的模块化头文件及实现11 m ...