【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 ...
随机推荐
- 编译时报错,找不到指定路径下的command,而路径是正确的。
使用的Fedora 18 64位的系统kernel,内核为3.6.10.按照要求使用yum install *** 安装各项工具. path路径使用提供的toolchain,各种路径也安装正确,却发现 ...
- 牛客网补题 New Game!(原Wannafly summer camp day2原题)
思路:这个题在秦皇岛的时候好像没有写出来,反正我是没有写出来,题解是听懂了:把直线和圆都看做一个结点,圆和直线用点到直线的距离与半径差求出来,圆和圆之间用点和点之间的距离和半径差表示,最后最短路跑一遍 ...
- Android : reletive layout
在兄弟的上下左右: android:layout_toRightOf="@id/btn1"/> android:layout_toLeftOf="@id/img1& ...
- HDU 1079 简单博弈
判断下一步能否到达必胜态,如果可以当前状态就是必败态,否则当前状态记为必胜态 #include <cstdio> #include <cstring> #include < ...
- [BZOJ2462] [BeiJing2011]矩阵模板(二维Hash)
传送门 二维哈希即可. 注意质数选的大一些,不然会超时. 还有插入的时候不判重居然比判重要快.. ——代码 #include <cstdio> int main() { ; ") ...
- hdu 4431 绝对值之和最小公式
/* 普通的二分不好写,反正我没写出来,这题核心需要求出绝对值最小公式 sum=|x+10|+|x+5|+|x+1|+|x-2|+|x-6|;sumx[1]=-10;sumx[2]=-15;sumx[ ...
- android view自定义
转载自:http://blog.csdn.net/iispring/article/details/50708044
- HDU 1754_I Hate It
[题意]给定区间求最大值 [分析]线段树单点更新 [代码] #include<cstdio> #include<iostream> using namespace std; c ...
- Layui选项卡、进度条、面板、徽章、时间线、辅助元素
Layui选项卡.进度条.面板.徽章.时间线.辅助元素 Tab选项卡 - 页面元素 导航菜单可应用于头部和侧边,Tab选项卡提供多套风格,支持响应式,支持删除选项卡等功能.面包屑结构简单,支持自 ...
- [bzoj2527][Poi2011]Meteors_整体二分_树状数组
Meteors bzoj-2527 Poi-2011 题目大意:题目链接. 注释:略. 想法: 首先答案可以离线,且具有单调性. 这里的单调性就是随着时间的推移,每个国家收集的陨石数增加. 不难想到整 ...