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. IDEA如何导入多个maven依赖的项目
  2. 图解YARN--大数据平台技术栈17
  3. php mysql备份成sql_单php文件实现备份MySQL导出为.sql数据库代码
  4. bzoj 1016: [JSOI2008]最小生成树计数【dfs+克鲁斯卡尔】
  5. 《从零开始学Swift》学习笔记(Day 33)——属性观察者
  6. [BUUCTF-pwn]——picoctf_2018_can_you_gets_me
  7. 提交spark的bug的地方
  8. 【剑指offer】面试题34:二叉树中和为某一值的路径(Java)
  9. LeetCode--256. 粉刷房子(动态规划)
  10. MySQL增删改查基础知识
  11. FPN相关问题学习记录
  12. Js封装组件 + Slots插槽
  13. Kali Linux 软件源和软件更新(留着自己看)
  14. 抑郁症患者自述:从那天起,我走进了地狱
  15. 结点电压法的c语言实现,节点电压法该如何理解_节点电压法例题
  16. 洛达悦虎1562M各个版本固件升级教程
  17. linux中的nm命令简介【转】
  18. JS事件的绑定和解绑
  19. 论文阅读:Cyber-security research
  20. nas修改启动盘sn和mac

热门文章

  1. node_modules
  2. Linux1:Linux概述
  3. SvsUtil.exe生成服务文件
  4. CSS中Float概念相关文章
  5. 都都的第一次自我游戏
  6. form表单提交不刷新页面的方法
  7. Android 隐藏Home键、返回键
  8. 在VisualState状态里更改Grid的列宽之类的
  9. 比较常用的几个正则表达式
  10. 【陷阱】交换排序中交换动作的陷阱