bzoj1977 [BeiJing2010组队]次小生成树 Tree——严格次小生成树
题目: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——严格次小生成树的更多相关文章
- 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- [bzoj1977][BeiJing2010组队]次小生成树 Tree——树上倍增+lca
Brief Description 求一个无向图的严格次小生成树. Algorithm Design 考察最小生成树的生成过程.对于一个非树边而言,如果我们使用这一条非树边去替换原MST的路径上的最大 ...
- bzoj1977 [BeiJing2010组队]次小生成树 Tree
和倍增法求lca差不多,维护每个点往上跳2^i步能到达的点,以及之间的边的最大值和次大值,先求出最小生成树,对于每个非树边枚举其端点在树上的路径的最大值,如果最大值和非树边权值一样则找次大值,然后维护 ...
- [BZOJ1977][BeiJing2010组队]次小生成树
题解: 首先要证明一个东西 没有重边的图上 次小生成树由任何一颗最小生成树替换一条边 但是我不会证啊啊啊啊啊啊啊 然后就很简单了 枚举每一条边看看能不能变 但有一个特殊情况就是,他和环上的最大值相等, ...
- 2018.09.15 bzoj1977:次小生成树 Tree(次小生成树+树剖)
传送门 一道比较综合的好题. 由于是求严格的次小生成树. 我们需要维护一条路径上的最小值和次小值. 其中最小值和次小值不能相同. 由于不喜欢倍增我选择了用树链剖分维护. 代码: #include< ...
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
[BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...
- 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 题意: 求严格次小生成树,即边权和不 ...
- [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 5168 Solved: 1668[S ...
随机推荐
- jenkins部署遇到离线问题如何解决
部署jenkins页面时遇到离线问题如何解决 部署jenkins遇到一个问题,然后告诉我你的jenkins已经离线,什么鬼,后来找了很多博客 后来自己终于验证成功了,也分享给大家,只需把https改为 ...
- (转)MySQL中的索引详讲
序言 之前写到MySQL对表的增删改查(查询最为重要)后,就感觉MySQL就差不多学完了,没有想继续学下去的心态了,原因可能是由于别人的影响,觉得对于MySQL来说,知道了一些复杂的查询,就够了,但是 ...
- <SpringMvc>入门三 参数绑定
1.get请求 <%--请求参数的绑定--%> <%--get请求参数--%> <a href="/param/testParam1?username=tom& ...
- linux动态库加载路径修改
1.在 /etc/ld.so.conf 文件中添加搜索路径,重启或者 ldconfig 生效: 2.在 /etc/ld.so.conf.d 目录下添加 *.conf 文件,其中可以添加搜索路径,重启获 ...
- 08.C语言:特殊函数
C语言:特殊函数 1.递归函数: 与普通函数比较,执行过程不同,该函数内部调用它自己,它的执行必须要经过两个阶段:递推阶段,回归阶段: 当不满足回归条件,不再递推: #include <stdi ...
- 洛谷 3870 [TJOI2009]开关
[题解] 线段树基础题.对于每个修改操作把相应区间的sum改为区间长度-sum即可. #include<cstdio> #include<algorithm> #include ...
- Windows Server 2008R2服务器IIS安装步骤
注意点: 添加ASP.NET ..NET 扩展性.CGI.ISAPI 扩展.ISAPI 筛选器,去掉 目录浏览(因为大多数网站用不到.) 如果需要用到asp则勾选asp,如果需要用shtm需要开启在服 ...
- 【Codeforces 1009C】Annoying Present
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 其实就是让你最后这n个数字的和最大. 加上的x没有关系.因为肯定都是加上n个x 所以直接加上就可以了 主要在于如何选取j 显然我们要找到一个位 ...
- 【Codeforces 1091D】New Year and the Permutation Concatenation
[链接] 我是链接,点我呀:) [题意] 把1~n的n!种排列依次连接成一个长度为nn!的序列. 让你在这个序列当中找长度为n的连续段,使得连续段中的数字的和为n(n-1)/2 输出符合要求的连续段的 ...
- poj 3164 最小树形图模板!!!
/* tle十几次,最后发现当i从1开始时,给环赋值时要注意啊! 最小树形图 */ #include<stdio.h> #include<string.h> #include& ...