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

  Time Limit: 10 Sec
  Memory Limit: 512 MB

Description

  小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当>小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成
树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 >EM,严格次小生成树选择的边集是 ES,那么需要满足:
  
            
这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。
  

Input

  第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z >表示,点 x 和点y之间有一条边,边的权值为z。。
  

Output

  包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
  

Sample Input 1

  5 6
  1 2 1
  1 3 2
  2 4 3
  3 5 4
  3 4 3
  4 5 6
  

Sample Output 1

  11
  

HINT

  数据中无向图无自环;
  50% 的数据N≤2 000 M≤3 000;
  80% 的数据N≤50 000 M≤100 000;
  100% 的数据N>≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。
  

题目地址: BZOJ 1977: [BeiJing2010组队]次小生成树

题解:

     
  先求出最小生成树,然后枚举每条不在该树上的边  
  求出此边两点的树上路径中小于此边长度的最大的边(题目要求严格次小)
  可用树上倍增解决,因为最大的边可能等于枚举的边,所以还要求出严格次大的边
  虽然很水但我还是被优先级和初值坑了三个小时QWQ
www.cnblogs.com/AGFghy/


AC代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct path
{int x,y,l;
}p[300005];
int n,m,num,f1,f2;
ll now,sum,n1,n2,ans;
int point[200005],len[200005],Next[200005],head[100005],fa[100005],dep[100005],mark[100005],f[100005][25];
ll mx1[100005][25],mx2[100005][25];
bool cmp(path p1,path p2)
{return p1.l<p2.l;
}
int find(int k)
{if (k!=fa[k]) return fa[k]=find(fa[k]);return k;
}
void add(int u,int v,int nl)
{num++;point[num]=v;len[num]=nl;Next[num]=head[u];head[u]=num;
}
void find(int now,int pre)
{dep[now]=dep[pre]+1;f[now][0]=pre;for (int i=head[now]; i!=-1; i=Next[i]){int v=point[i];if (v!=pre) {mx1[v][0]=len[i];find(v,now);}}
}
ll max(ll x,ll y)
{if (x>y) return x;return y;
}
ll min(ll x,ll y)
{if (x<y) return x;return y;
}
void lca(int u,int v)
{if (dep[u]<dep[v]) swap(u,v);int deep=dep[u]-dep[v];for (int i=0; i<=20; i++)if ((deep&(1<<i))>0) {n2=max(n2,mx2[u][i]);if (n1!=mx1[u][i]) n2=max(n2,min(n1,mx1[u][i]));n1=max(n1,mx1[u][i]);u=f[u][i];}for (int i=20; i>=0; i--)if (f[u][i]!=f[v][i]){n2=max(n2,mx2[u][i]);if (n1!=mx1[u][i]) n2=max(n2,min(n1,mx1[u][i]));n1=max(n1,mx1[u][i]);u=f[u][i];n2=max(n2,mx2[v][i]);if (n1!=mx1[v][i]) n2=max(n2,min(n1,mx1[v][i]));n1=max(n1,mx1[v][i]);v=f[v][i];}if (u!=v){n2=max(n2,mx2[u][0]);if (n1!=mx1[u][0]) n2=max(n2,min(n1,mx1[u][0]));n1=max(n1,mx1[u][0]);n2=max(n2,mx2[v][0]);if (n1!=mx1[v][0]) n2=max(n2,min(n1,mx1[v][0]));n1=max(n1,mx1[v][0]);} return;
}
int main()
{scanf("%d%d",&n,&m);for (int i=1; i<=n; i++)head[i]=-1;for (int i=1; i<=m; i++)scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].l);sort(p+1,p+m+1,cmp);for (int i=1; i<=n; i++)fa[i]=i;now=n-1;for (int i=1; i<=m; i++){f1=find(p[i].x);f2=find(p[i].y);if (f1!=f2){now--;fa[f2]=f1;sum+=p[i].l;mark[i]=1;add(p[i].x,p[i].y,p[i].l);add(p[i].y,p[i].x,p[i].l);if (now==0) break;}}memset(mx1,-1,sizeof(mx1));memset(mx2,-1,sizeof(mx2));find(1,0);for (int j=1; j<=20; j++)for (int i=1; i<=n; i++)if (f[i][j-1]){f[i][j]=f[f[i][j-1]][j-1];mx1[i][j]=max(mx1[i][j-1],mx1[f[i][j-1]][j-1]);if (mx1[i][j-1]!=mx1[f[i][j-1]][j-1]) mx2[i][j]=min(mx1[i][j-1],mx1[f[i][j-1]][j-1]);mx2[i][j]=max(mx2[i][j],max(mx2[i][j-1],mx2[f[i][j-1]][j-1]));}ans=1ll<<50;for (int i=1; i<=m; i++)if (mark[i]==0){n1=-1; n2=-1;lca(p[i].x,p[i].y);if (n1!=p[i].l) {now=sum+p[i].l-n1;ans=min(ans,now);}else if (n2!=-1){now=sum+p[i].l-n2;ans=min(ans,now);}}printf("%lld\n",ans);return 0;
}

转载于:https://www.cnblogs.com/AGFghy/p/9337654.html

BZOJ 1977: [BeiJing2010组队]次小生成树(Kruskal+树上倍增)相关推荐

  1. BZOJ 1977 [BeiJing2010组队]次小生成树 Tree

    严格次小生成树.一开始没有特批一圈都相等的情况,一直WA,十分难受. 先生成最小生成树,枚举每条非树边,连上它构成一个环,拆掉环上树边中最大的一条(若和该边相等则次大的一条)换上这条. 用倍增维护一条 ...

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

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

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

    https://www.lydsy.com/JudgeOnline/problem.php?id=1977 题解:次小生成树 /* *@Author: STZG *@Language: C++ */ ...

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

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

  5. 最小生成树(kruskal、prim、最小生成森林问题、严格次小生成树)

    整理的算法模板合集: ACM模板 目录 一.kruskal算法 二.prim算法 三.Boruvka算法 四.生成森林问题(K颗树) 五.最小生成树的唯一性 六.严格次小生成树 LCA优化的次小生成树 ...

  6. `Computer-Algorithm` 最小生成树MST,Prim,Kruskal,次小生成树

    Contents 最小生成树 Algorithm Prim Code Kruskal Prim&KruskalPrim \& KruskalPrim&Kruskal算法的性质 ...

  7. P4180-[BJWC2010]严格次小生成树【Kruskal,倍增】

    正题 题目链接:https://www.luogu.com.cn/problem/P4180 题目大意 nnn个点mmm条边的一张无向图,求它的严格次小生成树. 1≤n≤105,1≤m≤3×1051\ ...

  8. 【kruskal】【倍增】严格次小生成树(P4180)

    正题 P4180 题目大意 求严格次小生成树 解题思路 一定存在一种严格次小生成树,和最小生成树只差一条边,不然可以用一条最小生成树上的边代替,从而使边权和更小 那么可以先构造出最小生成树,然后枚举每 ...

  9. HDU4081(次小生成树)

    1.其中:枚举每条不在最小生成树上的边,并把这条边放到最小生成树上面,然后就一定形成环,那么我们将这条环中取出最长的一条路.最终我们得到的权值便是最小生成树的权值. Max[i][j]表示的最小生成树 ...

最新文章

  1. ulimit -n 修改
  2. 在Angular4中使用ng2-baidu-map详解
  3. SpringBoot中访问静态资源
  4. SwiftUI3优秀文章List 去掉左右间距问题
  5. HTML5废除元素,HTML5 与 HTML4 的区别(2) - 新增的元素和废除的元素
  6. 东南大学的计算机类和电子信息哪个专业好,东南大学王牌专业有哪些及专业排名...
  7. 数组指定位置添加元素_访问数组的任意位置元素的性能真的一样?
  8. 用AI算法分析光影看到盲点:这项MIT新研究偷学到二娃技能
  9. 【李宏毅2020 ML/DL】P74 Generative Adversarial Network | Basic Idea
  10. java 富文本 xss_Jsoup 防止富文本 XSS 攻击
  11. Struts2校验器(一)之规格文件
  12. JQuery提交表单
  13. 本特利330906-02-12-05-02-CN传感器
  14. 华为USG防火墙通过nat64 ipv6用户访问内网ipv4服务(原创,转发请注明出处)
  15. C++深入学习笔记—基础篇—个人银行账户管理程序
  16. switch结构详解
  17. android英语字典(源代码),android英语字典(内含源码哦)
  18. 宁夏召开外派教师家属新春慰问座谈会
  19. C++ Cstring类型使用
  20. git恢复误删代码或文件

热门文章

  1. 在线引入bootstrap包
  2. Python Selenium + phantomJS 模拟登陆教务管理系统 “抢课”
  3. jquery-ui里日期插件的使用
  4. puppet完全攻略(一)puppet应用原理及安装部署
  5. Struts2数据传输的背后机制:ValueStack(值栈)
  6. ArrayList源码分析(基于JDK1.6)
  7. Oracle Golden Gate 系列十五 -- GG Trails 说明
  8. 使用.net调用java的Web Services
  9. WF单元测试系列3:测试Activity的行为
  10. 发现自己的BLOG被转载了