题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1977

因为严格,所以要记录到 LCA 的一个次小值;

很快写好,然后改掉一堆错误后终于过了样例!然而交上去1WA;

又改了半天,还是WA,于是放弃,抄题解好久...

然而就在我调了一个小时终于锁定错误就在那个子函数里的时候才突然看到了自己的明显惊天大错误是怎么回事??!!!稍微改了一下下就完美AC。。。

不过还有点收获,把求各种层次的 f 放在 dfs 函数里会比单独拿出来再求一遍快 1000+ms 哦~

题解的写法是直接看 u 到 lca 和 v 到 lca 路上的值,而我是求 lca 的过程中求值的,还是喜欢我的写法;

题解的写法放在注释里了;

囧。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=1e5+,maxm=3e5+,inf=1e9;
int n,m,f[maxn][],dep[maxn],mx[maxn][],nmx[maxn][];//
int hd[maxn],ct,fa[maxn],d[maxn],mnn;
ll ans;//ll
bool vis[maxn],used[maxm];
struct P{int u,v,w;}e[maxm];
struct T{
int mx,nmx;
T(int x=,int n=):mx(x),nmx(n) {}
};
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxn<<];
bool cmp(P x,P y){return x.w<y.w;}
void add(int x,int y,int w){ed[++ct]=N(y,hd[x],w); hd[x]=ct;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void dfs(int x)
{
for (int i=; i<=; i++)//写在这里较快
{
if(dep[x]<(<<i))break;
f[x][i]=f[f[x][i-]][i-];
mx[x][i]=max(mx[x][i-],mx[f[x][i-]][i-]);
if (mx[x][i-]==mx[f[x][i-]][i-])
nmx[x][i]=max(nmx[x][i-],nmx[f[x][i-]][i-]);
else
nmx[x][i]=min(mx[x][i-],mx[f[x][i-]][i-]),
nmx[x][i]=max(nmx[x][i],nmx[x][i-]),
nmx[x][i]=max(nmx[x][i],nmx[f[x][i-]][i-]);
}
vis[x]=;
for(int i=hd[x],u;i;i=ed[i].nxt)
if(!vis[u=ed[i].to])
{
f[u][]=x; dep[u]=dep[x]+;
mx[u][]=ed[i].w;
// nmx[u][0]=ed[i].w;//无!
d[u]=ed[i].w;
dfs(u);
}
}
void init()
{
dep[]=; dfs();
// for(int j=1;j<=20;j++)
// for(int i=1;i<=n;i++)
// {
// int tmx=mx[f[i][j-1]][j-1],tnx=nmx[f[i][j-1]][j-1];
// f[i][j]=f[f[i][j-1]][j-1];
// mx[i][j]=max(mx[i][j-1],tmx);
// if(tmx>mx[i][j-1]) nmx[i][j]=max(mx[i][j-1],tnx);
// else if(tmx==mx[i][j-1]) nmx[i][j]=max(nmx[i][j-1],tnx);
// else nmx[i][j]=max(nmx[i][j-1],tmx);
// }
}
void ch(int &rmx,int &rnx,int tmx,int tnx)
{
if(tmx>rmx)
{
rnx=max(tnx,rmx);
rmx=tmx;
}
else if(tmx==rmx) rnx=max(tnx,rnx);
else rnx=max(rnx,tmx);
}
T lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int k=dep[x]-dep[y],rmx=-,rnx=-;
for(int i=;i>=;i--)
// if((1<<i)&k){rmx=mx[x][i]; rnx=nmx[x][i]; x=f[x][i];}//x放在后面修改!
if((<<i)&k){ch(rmx,rnx,mx[x][i],nmx[x][i]); x=f[x][i];}//!!!!!!囧
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])
{
ch(rmx,rnx,mx[x][i],nmx[x][i]);
ch(rmx,rnx,mx[y][i],nmx[y][i]);
x=f[x][i]; y=f[y][i]; //后面改!!
}
if(x!=y) ch(rmx,rnx,max(d[x],d[y]),min(d[x],d[y]));
return T(rmx,rnx);
}
//int LCA(int x,int y)
//{
// if(dep[x]<dep[y])swap(x,y);
// int k=dep[x]-dep[y];
// for(int i=20;i>=0;i--)
// if((1<<i)&k){rmx=mx[x][i]; rnx=nmx[x][i]; x=f[x][i];}
// for(int i=20;i>=0;i--)
// if(f[x][i]!=f[y][i])
// {
// x=f[x][i]; y=f[y][i];
// }
// if(x==y)return x;
// return f[x][0];
//}
//T work(int x,int lca)
//{
// T ret;
// int maxx1=-1,maxx2=-1;
// int d=dep[x]-dep[lca];
// for (int i=0; i<=20; i++)
// if (d&(1<<i))
// {
// ch(maxx1,maxx2,mx[x][i],nmx[x][i]);
// x=f[x][i];
// }
// ret.mx=maxx1,ret.nmx=maxx2;
// return ret;
//}
//T solve(int x)
//{
// T ret;
// int u=e[x].u,v=e[x].v,lca=LCA(u,v);
// T uu=work(u,lca);
// T vv=work(v,lca);
// ret.mx=max(uu.mx,vv.mx);
// if(uu.mx>vv.mx) ret.nmx=max(vv.mx,uu.nmx);
// else if(uu.mx==vv.mx) ret.nmx=max(vv.nmx,uu.nmx);
// else ret.nmx=max(uu.mx,vv.nmx);
// return ret;
//}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e+,e+m+,cmp);
for(int i=;i<=n;i++)fa[i]=i;
int cnt=;
for(int i=,u,v;i<=m;i++)
if(find(u=e[i].u)!=find(v=e[i].v))
{
cnt++;
fa[find(u)]=find(v);
used[i]=; ans+=e[i].w;
add(u,v,e[i].w); add(v,u,e[i].w);
if(cnt==n-)break;
}
init();
mnn=inf;
for(int i=;i<=m;i++)
{
if(used[i])continue;
int u=e[i].u,v=e[i].v;
T l=lca(u,v);
// T l=solve(i);
if(e[i].w==l.mx)mnn=min(mnn,e[i].w-l.nmx);
else mnn=min(mnn,e[i].w-l.mx);
}
printf("%lld",ans+mnn);
return ;
}

bzoj1977 [BeiJing2010组队]次小生成树 Tree——严格次小生成树的更多相关文章

  1. 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree

    Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...

  2. [bzoj1977][BeiJing2010组队]次小生成树 Tree——树上倍增+lca

    Brief Description 求一个无向图的严格次小生成树. Algorithm Design 考察最小生成树的生成过程.对于一个非树边而言,如果我们使用这一条非树边去替换原MST的路径上的最大 ...

  3. bzoj1977 [BeiJing2010组队]次小生成树 Tree

    和倍增法求lca差不多,维护每个点往上跳2^i步能到达的点,以及之间的边的最大值和次大值,先求出最小生成树,对于每个非树边枚举其端点在树上的路径的最大值,如果最大值和非树边权值一样则找次大值,然后维护 ...

  4. [BZOJ1977][BeiJing2010组队]次小生成树

    题解: 首先要证明一个东西 没有重边的图上 次小生成树由任何一颗最小生成树替换一条边 但是我不会证啊啊啊啊啊啊啊 然后就很简单了 枚举每一条边看看能不能变 但有一个特殊情况就是,他和环上的最大值相等, ...

  5. 2018.09.15 bzoj1977:次小生成树 Tree(次小生成树+树剖)

    传送门 一道比较综合的好题. 由于是求严格的次小生成树. 我们需要维护一条路径上的最小值和次小值. 其中最小值和次小值不能相同. 由于不喜欢倍增我选择了用树链剖分维护. 代码: #include< ...

  6. 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增

    [BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...

  7. BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )

    做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...

  8. 1977: [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...

  9. [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 5168  Solved: 1668[S ...

随机推荐

  1. Unity中播放带有alpha通道格式为Mp4的视频

    问题: Unity中实现播放透明的MP4视频时出现黑点 解决办法:    使用Unity自带的shader去除黑点 1:shader代码如下所示 Shader "Unlit/NewUnlit ...

  2. PHP 生成器Generators的入门理解和学习

    什么是生成器Generators 生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间.相反,你可以写一个生成器 ...

  3. 使用Postman Interceptor发送带cookie的请求一直loading的解决法案

    很多web网页开发人员都知道Postman限制由于chrome安全的限制,发不出带cookie和带有自定义头部标签的请求.想要发出由于chrome安全的限制,发不出带cookie和带有自定义头部标签的 ...

  4. 教你如何使用Python写游戏辅助脚本

    主要实现方式是通过图片的对比,在游戏中就行点击.运行程序需要以下东西. PIL: 图片处理模块     (python3 换成了 pillow)  下载地址: https://www.lfd.uci. ...

  5. RequestMapping注解_修饰类

    [使用RequestMapping映射请求] 1.Spring MVC使用 @RequestMapping 注解为控制器指定可以处理哪些URL请求. 2.在控制器的类定义及方法定义处都可以标注. @R ...

  6. mongodb shell之使用js(二)

    mongodb shell之使用js(二) mongodb shell不仅是个交互式shell,还能够使用js脚本进行访问. 使用js脚本进行交互的优点与缺点 (1)无需任何驱动或语言支持: (2)方 ...

  7. codevs1018 单词接龙

    题目描述 Description 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次), ...

  8. JAVA NIO 之Channel

    缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.Channel 通道就是将数据传输给 ByteBuffer 对象或者从 ByteBuffer 对象获取数据进行传输. Channel 用于在 ...

  9. SiteMesh2-示例工程

    了解SiteMesh的最佳方法是使用它.假设SiteMesh设置在您的Web应用程序中,本教程将展示如何掌握SiteMesh最强大的方面,如下所示装饰页面: 效果发生在第2步,其中Menu.jsp页面 ...

  10. MVC之查询demo

    上篇已经说过怎样建立MVC项目.这次主要讲述样例的实现. 其基本的功能就是从数据库中查询一些基本信息. 前边我们已经将实体引入到了项目中,这时Model目录中已经出现了我们建立的newsSystem. ...