BZOJ 1977 次小生成树
TM终于过了。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 300500
#define maxe 800500
#define inf 0x7fffffffffffffff
using namespace std;
struct edge
{
long long v,w,nxt;
}e[maxe];
struct edge_mp
{
long long u,v,w,flag;
}mp[maxe];
long long n,m,g[maxv],nume=,father[maxv],anc[maxv][],mx1[maxv][],mx2[maxv][],ans=,dx=inf,dis[maxv];
long long r1=,r2=;
bool cmp(edge_mp x,edge_mp y)
{
return x.w<y.w;
}
void addedge(long long u,long long v,long long w)
{
e[++nume].v=v;
e[nume].w=w;
e[nume].nxt=g[u];
g[u]=nume;
}
long long getfather(long long x)
{
if (father[x]!=x)
father[x]=getfather(father[x]);
return father[x];
}
void kruskal()
{
for (long long i=;i<=n;i++) father[i]=i;
sort(mp+,mp+m+,cmp);
for (long long i=;i<=m;i++)
{
long long u=mp[i].u,v=mp[i].v,w=mp[i].w;
if (getfather(u)!=getfather(v))
{
father[getfather(u)]=getfather(v);mp[i].flag=;ans+=w;
addedge(u,v,w);addedge(v,u,w);
}
}
}
void dfs(long long x,long long father)
{
for (long long i=g[x];i;i=e[i].nxt)
{
long long v=e[i].v;
if (v!=father)
{
anc[v][]=x;mx1[v][]=e[i].w;mx2[v][]=;
dis[v]=dis[x]+;
dfs(v,x);
}
}
}
void get_table()
{
for (long long e=;e<=;e++)
for (long long i=;i<=n;i++)
{
anc[i][e]=anc[anc[i][e-]][e-];
long long regis[];
regis[]=mx1[i][e-];regis[]=mx1[anc[i][e-]][e-];
regis[]=mx2[i][e-];regis[]=mx2[anc[i][e-]][e-];
sort(regis+,regis+);
mx1[i][e]=regis[];
for (long long j=;j>=;j--)
{
if (regis[j]==regis[j+]) continue;
else {mx2[i][e]=regis[j];break;}
}
}
} void get_ans(long long x)
{
long long u=mp[x].u,v=mp[x].v;r1=-;r2=-;
long long k1=-,k2=-,k3=-,k4=-;
if (dis[u]<dis[v]) swap(u,v);
if (dis[u]!=dis[v])
{
for (long long e=;e>=;e--)
{
long long pos=anc[u][e];
if ((dis[pos]>=dis[v]) && (pos>))
{
long long regis[];
regis[]=mx1[u][e];regis[]=mx2[u][e];regis[]=k1;regis[]=k2;
sort(regis+,regis+);
k1=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {k2=regis[i];break;}
}
u=pos;
}
}
}
if (u==v)
{
r1=k1;r2=k2;
return;
}
for (long long e=;e>=;e--)
{
long long posu=anc[u][e],posv=anc[v][e];
if (posu!=posv)
{
long long regis[];
regis[]=mx1[u][e];regis[]=mx2[u][e];regis[]=k1;regis[]=k2;
sort(regis+,regis+);
k1=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {k2=regis[i];break;}
}
regis[]=mx1[v][e];regis[]=mx2[v][e];regis[]=k3;regis[]=k4;
sort(regis+,regis+);
k3=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {k4=regis[i];break;}
}
u=posu;v=posv;
}
}
long long regis[];
regis[]=k1;regis[]=k2;regis[]=k3;regis[]=k4;regis[]=mx1[u][];regis[]=mx1[v][];
sort(regis+,regis+);
r1=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {r2=regis[i];break;}
}
}
int main()
{
scanf("%lld%lld",&n,&m);
for (long long i=;i<=m;i++)
{
scanf("%lld%lld%lld",&mp[i].u,&mp[i].v,&mp[i].w);
mp[i].flag=;
}
kruskal();
memset(mx1,,sizeof(mx1));
memset(mx2,,sizeof(mx2));
dfs(,);
get_table();
for (long long i=;i<=m;i++)
{
if (mp[i].flag) continue;
long long u=mp[i].u,v=mp[i].v,w=mp[i].w;
get_ans(i);
if (r1==mp[i].w)
{
if (r2==-) continue;
dx=min(dx,mp[i].w-r2);
}
else if (r1<mp[i].w) dx=min(dx,mp[i].w-r1);
}
printf("%lld\n",ans+dx);
return ;
}
BZOJ 1977 次小生成树的更多相关文章
- [BeiJing2010组队][BZOJ 1977]次小生成树 Tree
话说这个[BeiJing2010组队]是个什喵玩意? 这是一道严格次小生成树,而次小生成树的做法是层出不穷的 MATO IS NO.1 的博客里对两种算法都有很好的解释,值得拥有: (果然除我以外, ...
- BZOJ 1977 次小生成树(最近公共祖先)
题意:求一棵树的严格次小生成树,即权值严格大于最小生成树且权值最小的生成树. 先求最小生成树,对于每个不在树中的边,取两点间路径的信息,如果这条边的权值等于路径中的权值最大值,那就删掉路径中的次大值, ...
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
- BZOJ 1977 严格次小生成树(算竞进阶习题)
树上倍增+kruskal 要找严格次小生成树,肯定先要找到最小生成树. 我们先把最小生成树的边找出来建树,然后依次枚举非树边,容易想到一种方式: 对于每条非树边(u,v),他会与树上的两个点构成环,我 ...
- BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树
描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...
- 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- BZOJ 1977 严格次小生成树
小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小 ...
- bzoj 1977 洛谷P4180 严格次小生成树
Description: 给定一张N个节点M条边的无向图,求该图的严格次小生成树.设最小生成树边权之和为sum,那么严格次小生成树就是边权之和大于sum的最小的一个 Input: 第一行包含两个整数N ...
- 1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
随机推荐
- 【译】C++工程师需要掌握的10个C++11特性
原文标题:Ten C++11 Features Every C++ Developer Should Use 原文作者:Marius Bancila 原文地址:codeproject 备注:非直译,带 ...
- HDU 4027 Can you answer these queries?(线段树,区间更新,区间查询)
题目 线段树 简单题意: 区间(单点?)更新,区间求和 更新是区间内的数开根号并向下取整 这道题不用延迟操作 //注意: //1:查询时的区间端点可能前面的比后面的大: //2:优化:因为每次更新都 ...
- POJ 2140
#include<iostream> #include<stdio.h> using namespace std; int main() { int num; int i; i ...
- linux环境几个特殊的shell变量
特殊的shell变量: $0 获取当前执行的shell脚本的文件名 $n 获取当前执行的shell脚本的第n个参数值,n=1..9 $* 获取当前shell的所有参数 “$1 $2 $3 …注意 ...
- Qt之图形(Source和Dest相互覆盖的取舍,真的很方便)
源码 ... painter.drawImage(0, 0, destinationImage); painter.setCompositionMode(QPainter::Composition ...
- Java的Reference感觉很象C++的指针,但是区别是本质的
Java的Reference感觉很象C++的指针,但是区别是本质的 他们相同之处在于都是含有一个地址,但是在Java中你无法对这个地址进行任何数学运算,并且这个地址你不知道,是Java Runtime ...
- 人脸识别算法准确率最终超过了人类 The Face Recognition Algorithm That Finally Outperforms Humans
Everybody has had the experience of not recognising someone they know—changes in pose, illumination ...
- Data Base sqlServer基础知识
sqlServer 基础知识 大纲 创建数据库 1 创建表 2 备份表 3 删除表 4 修改表 5 查询出重复的数据 6 增删改查 7 添加约束 8 分页存储过程 9 排序 10 类型转换 11 ...
- 《Java编程那点事儿》读书笔记(五)——System,Integer,Calendar,Random和容器
System 1)arraycopy int[] a = {1.2.3.4}; int[] b = new int[5]; System.arraycopy(a,1,b,3,2); //把数组a中从下 ...
- android下使用smack需引入的包
compile 'org.igniterealtime.smack:smack-android:4.2.0-alpha1' compile 'org.igniterealtime.smack:smac ...