【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 ...
随机推荐
- (thinkPHP)PHP常用函数大全
usleep() 函数延迟代码执行若干微秒.unpack() 函数从二进制字符串对数据进行解包.uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID.time_sleep_until() ...
- ruby rspec安装
在rubymine里新建Rails application
- centOS7+mariadb+Nginx+PHP7.0 安装
1.前期准备工作 更新 yum 源,自带的源没有 PHP5.6 rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7 ...
- 用python爬取一张仓鼠图片
一. 找到一张仓鼠图片并复制一下它的url url='http://img.go007.com/2017/08/16/c407f5b732f4e748_2.jpg' 二. 调用urllib库 impo ...
- prometheus监控mysql
创建一个用于mysqld_exporter连接到MySQL的用户并赋予所需的权限 mysql> GRANT REPLICATION CLIENT, PROCESS ON *.* TO '; my ...
- C语言《一维数组的学习,冒泡排序》
#include<stdio.h> /* 一维数组的学习,冒泡排序 soulsjie 20170623 */ void main(){ int a[6]; int i,j,k; print ...
- JavaEE JDBC PreparedStatement
PreparedStatement @author ixenos PreparedStatement工作原理 注意:虽然mysql不支持PreparedStatement优化,但依然有预编译的实现! ...
- codeforces 363B
#include<stdio.h> #include<string.h> #define inf 999999999 #define N 151000 int a[N],c[N ...
- 2017-10-03-morning
#include <algorithm> #include <cstring> #include <cstdio> inline void read(int &am ...
- Eclipse使用Maven时,修改默认中央仓库后的配置报错找不到包的问题解决
一般在公司内容配置Maven时会在settings.xml文件下配置私服nexus地址,那么修改完之后在Eclipse中如果不指定用户目录级别的settings.xml文件会出现找不到包的问题. se ...