[Beijing2010组队]次小生成树Tree
小C最近学了很多最小生成树的算法,Prim算法、Kurskal算法、消圈算法等等。正当小C洋洋得意之时,小P又来泼小C冷水了。小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是EM,严格次小生成树选择的边集是ES,那么需要满足:(value(e)表示边e的权值) \sum_{e \in E_M}value(e)<\sum_{e \in E_S}value(e)∑e∈EMvalue(e)<∑e∈ESvalue(e)
这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。
输入输出格式
输入格式:
第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。
输出格式:
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
输入输出样例
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
11
说明
数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。
跑个最小生成树然后LCA维护路径最大和次大(严格)边即可,利用了最小生成树的环性质。
(我就想请问出题人忘了给边排序是怎么能过样例hhhh,mdzz查错了一个点最后发现没给边排序)
code:
#include<bits/stdc++.h>
#define ll long long
#define maxn 100005
using namespace std;
ll base=0;
struct lines{
int u,v,w;
bool operator <(const lines &U)const{
return w<U.w;
}
}l[maxn*3];
struct node{
int m,cm;
node operator +(const node &u)const{
node r;
r.m=max(m,u.m);
r.cm=max(cm,u.cm);
if(m<r.m) r.cm=max(r.cm,m);
if(u.m<r.m) r.cm=max(r.cm,u.m);
return r;
}
};
const int inf=1e9;
bool choose[maxn*3];
int ci[30],ans=inf;
int to[maxn*2],ne[maxn*2];
int val[maxn*2],cnt=0,n,m;
int f[maxn][20];
node g[maxn][20];
int hd[maxn],p[maxn],dep[maxn]; int ff(int x){
return p[x]==x?x:(p[x]=ff(p[x]));
} inline void add(lines e){
to[++cnt]=e.v,ne[cnt]=hd[e.u],val[cnt]=e.w,hd[e.u]=cnt;
to[++cnt]=e.u,ne[cnt]=hd[e.v],val[cnt]=e.w,hd[e.v]=cnt;
} inline void kruscal(){
for(int i=1;i<=n;i++) p[i]=i;
int fa,fb,tot=0;
sort(l+1,l+m+1); n--;
for(int i=1;i<=m;i++){
fa=ff(l[i].u),fb=ff(l[i].v);
if(fa!=fb){
tot++,choose[i]=1;
base+=(ll)l[i].w;
add(l[i]),p[fa]=fb;
if(tot==n) break;
}
}
n++;
} void dfs(int x,int fa){
for(int i=1;ci[i]<=dep[x];i++){
g[x][i]=g[x][i-1]+g[f[x][i-1]][i-1];
f[x][i]=f[f[x][i-1]][i-1];
} for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){
dep[to[i]]=dep[x]+1;
f[to[i]][0]=x;
g[to[i]][0]=(node){val[i],0};
dfs(to[i],x);
}
} inline node LCAMAX(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int dt=dep[x]-dep[y];
node an=(node){0,0};
for(int i=0;ci[i]<=dt;i++) if(ci[i]&dt){
an=an+g[x][i];
x=f[x][i];
} if(x==y) return an; int s=log(dep[x])/log(2)+1;
for(;s>=0;s--){
if(ci[s]>dep[x]) continue;
if(f[x][s]!=f[y][s]){
an=an+g[x][s]+g[y][s];
x=f[x][s],y=f[y][s];
}
} return an+g[x][0]+g[y][0];
} inline void solve(){
dep[1]=0;
dfs(1,0); node tmp;
for(int i=1;i<=m;i++) if(!choose[i]){
tmp=LCAMAX(l[i].u,l[i].v);
// printf("%d %d %d\n",i,tmp.m,tmp.cm);
if(tmp.m<l[i].w) ans=min(ans,l[i].w-tmp.m);
else ans=min(ans,l[i].w-tmp.cm);
}
} int main(){
ci[0]=1;
for(int i=1;i<=20;i++) ci[i]=ci[i-1]<<1;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d",&l[i].u,&l[i].v,&l[i].w); kruscal();
solve(); cout<<(ll)ans+base<<endl;
return 0;
}
[Beijing2010组队]次小生成树Tree的更多相关文章
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
- 1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
[BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...
- [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 5168 Solved: 1668[S ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- (luogu4180) [Beijing2010组队]次小生成树Tree
严格次小生成树 首先看看如果不严格我们怎么办. 非严格次小生成树怎么做 由此,我们发现一个结论,求非严格次小生成树,只需要先用kruskal算法求得最小生成树,然后暴力枚举非树边,替换路径最大边即可. ...
- BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树
描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...
- 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并
题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...
随机推荐
- String类型的方法使用
String.equals()方法源代码: public boolean equals(Object anObject) { if (this == anObject) { return true; ...
- MyBatis中使用OGNL表达式与操作符
String与基本数据类型 _parameter 自定义类型(对象) 属性名 集合 数组 array List list Map _parameter 获取集合中的一条数据 数组 array[索引] ...
- 【bzoj3289】Mato的文件管理 离散化+莫队算法+树状数组
原文地址:http://www.cnblogs.com/GXZlegend/p/6805224.html 题目描述 Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份 ...
- What is a Microsoft Failover Cluster Virtual Adapter
What is a Microsoft Failover Cluster Virtual Adapter anyway? A question often asked is, "What i ...
- 【ZOJ4062】Plants vs. Zombies(二分)
题意:有n个植物排成一排,标号为1-n,每株植物有自己的生长速度ai,每对植物浇一次水,该株植物就长高ai, 现在机器人从第0个格子出发,每次走一步,不能停留,每一步浇一次水,总共可以走m步,问最矮的 ...
- 写一个system.data.entity的simpledatarepo,实现crudq这些功能,不需要引入entityframework,直接可以使用,用到objectset
note:you can delete reference of entityframework when using this classes.it`s just a simple repohelp ...
- 积木大赛(NOIP2013)(纯贪心+模拟)
好吧,这道题也是..醉了. 其实题目编程挺水的,但是贪心过程不好想. 原题传送门 这道题对于任何一个点a[i]如果a[i]<a[i-1]的话,那么假设a[i-1]的高度为X,a[i]的高度为y, ...
- Android NDK使用
1. 介绍 这里主要想记录一下Android NDK开发C程序的使用方法 2. ndk下载 到google官网或者国内镜像网站下载android-ndk形如: android-ndk-r<ve ...
- c# GDI画图 双缓冲画图分析
双缓冲绘图分析 1.Windows 绘图原理 我们在 Windows 环境下看到各种元素,如菜单.按钮.窗口.图像,从根本上说,都是“画”出来的.这时的屏幕,就相当于一块黑板,而 Windows ...
- windows 2012(64位) IIS配置asp程序 500 - 内部服务器错误。您查找的资源存在问题,因而无法显示。
在网上找了很久,包括常规的设置父路径之类的,一直都不可以,搞了一晚上毫无成就感,第二天早上无意中看到一篇文章,说到点子上了,非常感谢.源地址已经找不到了,我把大概的问题截图说明一下. 方法如下:1.打 ...