BZOJ 1977 次小生成树
TM终于过了。。。。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #define maxv 300500
- #define maxe 800500
- #define inf 0x7fffffffffffffff
- using namespace std;
- struct edge
- {
- long long v,w,nxt;
- }e[maxe];
- struct edge_mp
- {
- long long u,v,w,flag;
- }mp[maxe];
- long long n,m,g[maxv],nume=,father[maxv],anc[maxv][],mx1[maxv][],mx2[maxv][],ans=,dx=inf,dis[maxv];
- long long r1=,r2=;
- bool cmp(edge_mp x,edge_mp y)
- {
- return x.w<y.w;
- }
- void addedge(long long u,long long v,long long w)
- {
- e[++nume].v=v;
- e[nume].w=w;
- e[nume].nxt=g[u];
- g[u]=nume;
- }
- long long getfather(long long x)
- {
- if (father[x]!=x)
- father[x]=getfather(father[x]);
- return father[x];
- }
- void kruskal()
- {
- for (long long i=;i<=n;i++) father[i]=i;
- sort(mp+,mp+m+,cmp);
- for (long long i=;i<=m;i++)
- {
- long long u=mp[i].u,v=mp[i].v,w=mp[i].w;
- if (getfather(u)!=getfather(v))
- {
- father[getfather(u)]=getfather(v);mp[i].flag=;ans+=w;
- addedge(u,v,w);addedge(v,u,w);
- }
- }
- }
- void dfs(long long x,long long father)
- {
- for (long long i=g[x];i;i=e[i].nxt)
- {
- long long v=e[i].v;
- if (v!=father)
- {
- anc[v][]=x;mx1[v][]=e[i].w;mx2[v][]=;
- dis[v]=dis[x]+;
- dfs(v,x);
- }
- }
- }
- void get_table()
- {
- for (long long e=;e<=;e++)
- for (long long i=;i<=n;i++)
- {
- anc[i][e]=anc[anc[i][e-]][e-];
- long long regis[];
- regis[]=mx1[i][e-];regis[]=mx1[anc[i][e-]][e-];
- regis[]=mx2[i][e-];regis[]=mx2[anc[i][e-]][e-];
- sort(regis+,regis+);
- mx1[i][e]=regis[];
- for (long long j=;j>=;j--)
- {
- if (regis[j]==regis[j+]) continue;
- else {mx2[i][e]=regis[j];break;}
- }
- }
- }
- void get_ans(long long x)
- {
- long long u=mp[x].u,v=mp[x].v;r1=-;r2=-;
- long long k1=-,k2=-,k3=-,k4=-;
- if (dis[u]<dis[v]) swap(u,v);
- if (dis[u]!=dis[v])
- {
- for (long long e=;e>=;e--)
- {
- long long pos=anc[u][e];
- if ((dis[pos]>=dis[v]) && (pos>))
- {
- long long regis[];
- regis[]=mx1[u][e];regis[]=mx2[u][e];regis[]=k1;regis[]=k2;
- sort(regis+,regis+);
- k1=regis[];
- for (long long i=;i>=;i--)
- {
- if (regis[i]==regis[i+]) continue;
- else {k2=regis[i];break;}
- }
- u=pos;
- }
- }
- }
- if (u==v)
- {
- r1=k1;r2=k2;
- return;
- }
- for (long long e=;e>=;e--)
- {
- long long posu=anc[u][e],posv=anc[v][e];
- if (posu!=posv)
- {
- long long regis[];
- regis[]=mx1[u][e];regis[]=mx2[u][e];regis[]=k1;regis[]=k2;
- sort(regis+,regis+);
- k1=regis[];
- for (long long i=;i>=;i--)
- {
- if (regis[i]==regis[i+]) continue;
- else {k2=regis[i];break;}
- }
- regis[]=mx1[v][e];regis[]=mx2[v][e];regis[]=k3;regis[]=k4;
- sort(regis+,regis+);
- k3=regis[];
- for (long long i=;i>=;i--)
- {
- if (regis[i]==regis[i+]) continue;
- else {k4=regis[i];break;}
- }
- u=posu;v=posv;
- }
- }
- long long regis[];
- regis[]=k1;regis[]=k2;regis[]=k3;regis[]=k4;regis[]=mx1[u][];regis[]=mx1[v][];
- sort(regis+,regis+);
- r1=regis[];
- for (long long i=;i>=;i--)
- {
- if (regis[i]==regis[i+]) continue;
- else {r2=regis[i];break;}
- }
- }
- int main()
- {
- scanf("%lld%lld",&n,&m);
- for (long long i=;i<=m;i++)
- {
- scanf("%lld%lld%lld",&mp[i].u,&mp[i].v,&mp[i].w);
- mp[i].flag=;
- }
- kruskal();
- memset(mx1,,sizeof(mx1));
- memset(mx2,,sizeof(mx2));
- dfs(,);
- get_table();
- for (long long i=;i<=m;i++)
- {
- if (mp[i].flag) continue;
- long long u=mp[i].u,v=mp[i].v,w=mp[i].w;
- get_ans(i);
- if (r1==mp[i].w)
- {
- if (r2==-) continue;
- dx=min(dx,mp[i].w-r2);
- }
- else if (r1<mp[i].w) dx=min(dx,mp[i].w-r1);
- }
- printf("%lld\n",ans+dx);
- return ;
- }
BZOJ 1977 次小生成树的更多相关文章
- [BeiJing2010组队][BZOJ 1977]次小生成树 Tree
话说这个[BeiJing2010组队]是个什喵玩意? 这是一道严格次小生成树,而次小生成树的做法是层出不穷的 MATO IS NO.1 的博客里对两种算法都有很好的解释,值得拥有: (果然除我以外, ...
- BZOJ 1977 次小生成树(最近公共祖先)
题意:求一棵树的严格次小生成树,即权值严格大于最小生成树且权值最小的生成树. 先求最小生成树,对于每个不在树中的边,取两点间路径的信息,如果这条边的权值等于路径中的权值最大值,那就删掉路径中的次大值, ...
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
- BZOJ 1977 严格次小生成树(算竞进阶习题)
树上倍增+kruskal 要找严格次小生成树,肯定先要找到最小生成树. 我们先把最小生成树的边找出来建树,然后依次枚举非树边,容易想到一种方式: 对于每条非树边(u,v),他会与树上的两个点构成环,我 ...
- BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树
描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...
- 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- BZOJ 1977 严格次小生成树
小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小 ...
- bzoj 1977 洛谷P4180 严格次小生成树
Description: 给定一张N个节点M条边的无向图,求该图的严格次小生成树.设最小生成树边权之和为sum,那么严格次小生成树就是边权之和大于sum的最小的一个 Input: 第一行包含两个整数N ...
- 1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
随机推荐
- vc++ 获取当前用户名
#include<afxwin.h> #include <stdio.h> int main(void) { char userName[MAX_PATH]; unsigned ...
- Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)
第一次看到段更斐波那契数列的,整个人都不会好了.事后看了题解才明白了一些. 首先利用二次剩余的知识,以及一些数列递推式子有下面的 至于怎么解出x^2==5(mod 10^9+9),我就不知道了,但是要 ...
- java 反射创建对象并传入参数
/* * 通过反射创建带参数的对象 */ public Object Creatobject(String ClassPath, Object[] Params) throws Exception { ...
- lintcode:组成最大的数
最大数 给出一组非负整数,重新排列他们的顺序把他们组成一个最大的整数. 注意事项 最后的结果可能很大,所以我们返回一个字符串来代替这个整数. 样例 给出 [1, 20, 23, 4, 8],返回组合最 ...
- run fsck manually
就出现unexpected inconsistency run fsck manually这个问题了. 磁盘出问题,需要用 Fsck修复... 解决方案: 在命令行输入#mount | grep ”o ...
- 一些时间的概念与区分(UTC、GMT、LT、TAI等)
UT - 世界时 Universal Time世界时是最早的时间标准.在1884年,国际上将1s确定为全年内每日平均长度的1/8.64×104.以此标准形成的时间系统,称为世界时,即 UT1.1972 ...
- Haproxy均衡负载部署和配置文件详解
HAproxy均衡负载部署和配置文件详解 HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.根据官方数据,其最高极限支持10G ...
- iOS 开发--添加工程
文/Bison(简书作者)原文链接:http://www.jianshu.com/p/dd71e15df5d0著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 第一部分,配置项目 在此只 ...
- 【重走Android之路】【番外篇】关于==和equals
[重走Android之路][番外篇]关于==和equals 在实际的编程当中,经常会使用==和equals来判断变量是否相同.但是这两种比较方式也常常让人搞得云里雾里摸不着头脑.下面是我个人做的总 ...
- JVM垃圾回收机制总结(1) :一些概念
数据类型 Java虚拟机中,数据类型可以分为两类:基本类型 和引用类型 .基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对象本 ...