LOJ10068

这是严格次小生成树的模板题~~

我们首先考虑非严格次小生成树(看这篇):
可以证明,只要更改原图一条边就是满足条件的最优解:
首先我们假设加入一条边E,则最小生成树上形成了一个环,贪心的想法,我们会选择环中最长的一边替换掉

假如再添加一条边E_(显然E_>=E)

  • 若E_不在该环中,由于原图已为最小生成树,答案绝不会变小
  • 若E_在该环中,由于E_>=E,答案也不会变好

这样就证明了只需替换一条边
接下来考虑如何快速找出环上的最大边
显然可以分成两段:
x———–>LCA(x,y)
y———–>LCA(x,y)
既然都扯上LCA了,那么在LCA同时顺便刷答案即可
就像这样:

void DFS(int x,int da,int va){dep[x]=dep[da]+1,up[x][0]=da,p[x][0]=va;for(int i=1;(1<<i)<=dep[x];i++) up[x][i]=up[up[x][i-1]][i-1],p[x][i]=Max(p[x][i-1],p[up[x][i-1]][i-1]);for(int j=lnk[x];j;j=nxt[j]) if(son[j]!=da) DFS(son[j],x,w[j]);
}
int LCA(int x,int y){int now=0;if(dep[x]<dep[y]) swap(x,y);while(dep[x]>dep[y]) now=Max(now,p[x][pow[dep[x]-dep[y]]-1]),x=up[x][pow[dep[x]-dep[y]]-1];if(x==y) return now;for(int k=pow[dep[x]];k>=0;k--)if(up[x][k]!=up[y][k])now=Max(Max(p[x][k],p[y][k]),now),x=up[x][k],y=up[y][k];return Max(Max(p[x][0],p[y][0]),now);
}

再考虑如何求严格的。。
即当环中最大边==添入的边时,该怎么办
还是贪心想法,取严格次大边呗!
不过写起来真心爽
预处理:

#define Up up[x][i-1]
int dep[maxn],up[maxn][Log],val[maxn][Log],vll[maxn][Log];//val最大,vll严格次大
void DFS(int x,int dad){
    dep[x]=dep[dad]+1,up[x][0]=dad;
    for(__R int i=1;Pow[i]+1<=dep[x];i++){        up[x][i]=up[Up][i-1];
        if(val[x][i-1]>val[Up][i-1]){            val[x][i]=val[x][i-1];
            vll[x][i]=(vll[x][i-1]>val[Up][i-1]?vll[x][i-1]:val[Up][i-1]);//此时vll[x][i-1]!=val[x][i-1]且val[Up][i-1]!=val[x][i-1](val[Up][i-1]<val[x][i-1])
        }else{            val[x][i]=val[Up][i-1];
            if(vll[Up][i-1]>=val[x][i-1]) vll[x][i]=vll[Up][i-1];//vll[Up][i-1]必!=val[Up][i-1]
              else if(val[x][i-1]!=val[x][i]) vll[x][i]=val[x][i-1];//严格
                else vll[x][i]=(vll[x][i-1]>vll[Up][i-1]?vll[x][i-1]:vll[Up][i-1]);//vll显然是严格小于的
        }
    }
    for(__R int j=lnk[x];j;j=nxt[j])if(son[j]!=dad) val[son[j]][0]=w[j],vll[son[j]][0]=INF,DFS(son[j],x);
}

询问比较简单(copy地巨爽)

int LCA(int x,int y,int p){int D=INF,t;if(dep[x]<dep[y]) swap(x,y);while(dep[x]>dep[y]){if(val[x][t=LoG[dep[x]-dep[y]]-1]!=p) D=val[x][t]>D?val[x][t]:D;else D=vll[x][t]>D?vll[x][t]:D;x=up[x][t];}if(x==y) return D;for(__R int k=LoG[dep[x]]-1;k>=0;k--)if(up[x][k]!=up[y][k]){if(val[x][k]!=p) D=val[x][k]>D?val[x][k]:D;else D=vll[x][k]>D?vll[x][k]:D;if(val[y][k]!=p) D=val[y][k]>D?val[y][k]:D;else D=vll[y][k]>D?vll[y][k]:D;x=up[x][k],y=up[y][k];}__R int k=0;if(val[x][k]!=p) D=val[x][k]>D?val[x][k]:D;else D=vll[x][k]>D?vll[x][k]:D;if(val[y][k]!=p) D=val[y][k]>D?val[y][k]:D;else D=vll[y][k]>D?vll[y][k]:D;return D;
}

然后就可以了。。
复杂度O(N∗logN+E∗logN)O(N∗logN+E∗logN)O(N*log_N+E*log_N)

#include<bits/stdc++.h>
#define gt() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
#define Up up[x][i-1]
#define LL long long
#define __R register
using namespace std;
static char buf[1000000],*p1=buf,*p2=buf;
const int maxE=(3e5)+5,maxn=(1e5)+5,Log=22,INF=-(2e9);
int n,m,fa[maxn],Pow[Log+5],LoG[maxn];bool vis[maxE];LL Ans=(LL)1<<60,S;
int tot,son[maxn<<1],nxt[maxn<<1],w[maxn<<1],lnk[maxn];
void add_e(int x,int y,int z){son[++tot]=y,w[tot]=z,nxt[tot]=lnk[x],lnk[x]=tot;}
struct Edges{int x,y,w;bool operator <(const Edges b)const{return w<b.w;}
}E[maxE];
int read(){int ret=0;char ch=gt();while(ch<'0'||ch>'9') ch=gt();while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();return ret;
}
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
int dep[maxn],up[maxn][Log],val[maxn][Log],vll[maxn][Log];//val最大,vll严格次大
void DFS(int x,int dad){dep[x]=dep[dad]+1,up[x][0]=dad;for(__R int i=1;Pow[i]+1<=dep[x];i++){up[x][i]=up[Up][i-1];if(val[x][i-1]>val[Up][i-1]){val[x][i]=val[x][i-1];vll[x][i]=(vll[x][i-1]>val[Up][i-1]?vll[x][i-1]:val[Up][i-1]);//此时vll[x][i-1]!=val[x][i-1]且val[Up][i-1]!=val[x][i-1](val[Up][i-1]<val[x][i-1])}else{val[x][i]=val[Up][i-1];if(vll[Up][i-1]>=val[x][i-1]) vll[x][i]=vll[Up][i-1];//vll[Up][i-1]必!=val[Up][i-1] else if(val[x][i-1]!=val[x][i]) vll[x][i]=val[x][i-1];//严格 else vll[x][i]=(vll[x][i-1]>vll[Up][i-1]?vll[x][i-1]:vll[Up][i-1]);//vll显然是严格小于的 }}for(__R int j=lnk[x];j;j=nxt[j])if(son[j]!=dad) val[son[j]][0]=w[j],vll[son[j]][0]=INF,DFS(son[j],x);
}
int LCA(int x,int y,int p){int D=INF,t;if(dep[x]<dep[y]) swap(x,y);while(dep[x]>dep[y]){if(val[x][t=LoG[dep[x]-dep[y]]-1]!=p) D=val[x][t]>D?val[x][t]:D;else D=vll[x][t]>D?vll[x][t]:D;x=up[x][t];}if(x==y) return D;for(__R int k=LoG[dep[x]]-1;k>=0;k--)if(up[x][k]!=up[y][k]){if(val[x][k]!=p) D=val[x][k]>D?val[x][k]:D;else D=vll[x][k]>D?vll[x][k]:D;if(val[y][k]!=p) D=val[y][k]>D?val[y][k]:D;else D=vll[y][k]>D?vll[y][k]:D;x=up[x][k],y=up[y][k];}__R int k=0;if(val[x][k]!=p) D=val[x][k]>D?val[x][k]:D;else D=vll[x][k]>D?vll[x][k]:D;if(val[y][k]!=p) D=val[y][k]>D?val[y][k]:D;else D=vll[y][k]>D?vll[y][k]:D;return D;
}
int main(){n=read(),m=read();for(__R int i=1;i<=m;i++) E[i]=(Edges){read(),read(),read()};sort(E+1,E+1+m);for(__R int i=0;(Pow[i]=1<<i)<=n;i++);for(__R int i=1;i<=n;i++) LoG[i]=LoG[i-1]+(Pow[LoG[i-1]]==i),fa[i]=i;for(__R int i=1,fx,fy;i<=m;i++)if((fx=getfa(E[i].x))!=(fy=getfa(E[i].y))){fa[fx]=fy,S+=E[i].w,vis[i]=1;add_e(E[i].x,E[i].y,E[i].w),add_e(E[i].y,E[i].x,E[i].w);}DFS(1,0);LL now;for(__R int i=1;i<=m;i++) if(!vis[i]&&(now=S-LCA(E[i].x,E[i].y,E[i].w)+E[i].w)<Ans) Ans=now;printf("%lld\n",Ans);return 0;
}

LOJ10068(BZOJ1977)(Luogu4180)相关推荐

  1. BZOJ1977: [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree 题意:求严格次小生成树 我为什么要单独发这篇呢 因为愚蠢的我不停换写法最后发现是因为没开long long所以wa掉的 很简单,次小生成 ...

  2. POJ1679 Luogu4180 次小生成树

    The Unique MST Given a connected undirected graph, tell if its minimum spanning tree is unique. Defi ...

  3. (luogu4180) [Beijing2010组队]次小生成树Tree

    严格次小生成树 首先看看如果不严格我们怎么办. 非严格次小生成树怎么做 由此,我们发现一个结论,求非严格次小生成树,只需要先用kruskal算法求得最小生成树,然后暴力枚举非树边,替换路径最大边即可. ...

  4. BZOJ1977 [BJOI2010]次小生成树

    题目蓝链 Solution 考虑首先建出一棵最小生成树,然后再枚举所有其他的边.然后直接查询这条边对应在树上的两点之间的链上最大值和次大值,因为要保证严格次小.然后用查询的值更新一下答案 维护一条链上 ...

  5. (Bzoj1977)次小生成树

    试题描述 小C最近学了很多最小生成树的算法,Prim算法. Kurskal算法.消圈算法等,正当小C 得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这次 生成树还得是严 ...

  6. 算法学习之路和程序员(技术)学习必读书籍

    原文链接:http://lucida.me/blog/on-learning-algorithms/ 转 算法学习之路和程序员(技术)学习必读书籍 2015年05月26日 09:46:56 阅读数:1 ...

  7. OI每周刷题记录——lrllrl

    看这标题就知道我是模仿的hzwer大佬,远程%%% 大佬的OI经历让蒟蒻我深受感触,为了晚一些AFO本蒟蒻也得加油了 从高二上期第一周开始计数,每个星期天更一次,一直更到我AFO 如果这是我此生最后一 ...

  8. 《信息学奥赛一本通 提高篇》 第四部分 数据结构 第4章 倍增求LCA

    例题1 点的距离 信息学奥赛一本通(C++版)在线评测系统 例题2 暗的连锁(Poj3417) 信息学奥赛一本通(C++版)在线评测系统 LOj10131 暗的连锁_juruo_xlh-CSDN博客 ...

最新文章

  1. Java项目:实现个人博客系统(java+springboot+mybatis+redis+vue+elementui+Mysql)
  2. CSS基本选择器(元素选择器、类选择器、id选择器)
  3. MySQL 查看执行计划
  4. POJ - 2352 Stars(线段树/树状数组)
  5. Angular module加载的原理研究
  6. ES11新特性_BigInt---JavaScript_ECMAScript_ES6-ES11新特性工作笔记066
  7. 2015年上海现场赛重现 (A几何, K暴力搜索)
  8. 自学python到什么程度可以找工作-Python学到什么程度就可以找工作?
  9. net.sf.json Sring转JSON对象 数据精度丢失
  10. Matlab实现GM(1,1)模型(源代码)
  11. MCE | 线粒体和能量代谢的关系
  12. Learn Git Branching 答案汇总
  13. excel打开html非常慢,excel打开速度很慢的解决方法
  14. 形容词,名词记忆(三):ment, ent后缀常用词
  15. 用外部html圆形里装数字,如何使用CSS用圆圈包围数字?
  16. 简析王者荣耀的匹配机制
  17. 关于系统开发的小总结
  18. 1号店架构师王富平:一号店用户画像系统实践
  19. 投资组合的有效边界及基于目标函数的组合优化
  20. Linux常用命令帅哥特供版

热门文章

  1. (分享)视频压缩Free Video Compressor 汉化版/中文版【全网唯一】
  2. 关于粒子群算法的两种惯性权重
  3. RISV-Reader小结
  4. Simhash算法介绍和应用内容
  5. 东北大学《材料现代研究方法》复习题及答案
  6. CAD图形的缩放——放大镜
  7. win10如何设置锁屏后不熄屏
  8. 单个像素代表的实际物理尺寸
  9. linux一句话精彩问答 (转贴)
  10. 学习方法之03复述记忆法,让你不再死记硬背