[BJOI]2010 严格次小生成树
来源:互联网 发布:js 中国地图 编辑:程序博客网 时间:2024/06/11 05:29
题意:给出一个无向图,求其严格最小生成树(废话) n <= 100000
分析:
一般的做法:在MST上断一条边,再次求MST,取最小的值,最快的速度应该是堆优化Prim算法 O(n^2 log2n),但是在本题中显然会TLE
题目很裸,只能直接看这个模型。
次小的生成树,一定是MST上加了某一条边,形成了一个环,接着再删去某一条边得来的。加的边肯定没有特殊的决策,只好枚举,但是删去的边有玄机。由MST的性质,加上的这一条边肯定不小于环上的边,如果它比环上最大的边要大,那么答案一定就是 MST + 这条边 - 环上的边 ,可是如果它们相等呢?显然,求环上次大的边。
可是怎么快速求出”一条边连接两个顶点在MST上形成的环的最大值和次大值?”
嗯..这是个很常见的模型,倍增法可以在O(log2n)的时间内解决
Ps:第一次做,求出次大的还真不好处理,这里值得注意一下
/*I am firing!*/#include<cstdio>#include<cstring>#include<climits>#include<iostream>#include<algorithm>using namespace std;typedef int _int;#define int long longtypedef long long LL;const int Lim = 100005;int n , m , cnt_edge , maxx1 , maxx2;LL Ans , Ans_second = LLONG_MAX / 2;int dep[Lim] , Max[Lim][20] , sec[Lim][20] , fa[Lim][20];int head[Lim] , prt[Lim];bool vst[Lim * 3];struct St {int next , to , val;} e[Lim * 3];struct E { int a , b , c; friend bool operator < (const E & A , const E & B) {return A.c < B.c;}} edge[Lim * 3];void Addstar(int x , int y , int z) {e[++cnt_edge] = (St) {head[x] , y , z}; head[x] = cnt_edge;}int Getfather(int x) {return x == prt[x] ? x : prt[x] = Getfather(prt[x]);}void Dfs(int x){ for(int i=head[x] ; i ; i=e[i].next) { int y = e[i].to; if(y == fa[x][0]) continue; dep[y] = dep[x] + 1; Max[y][0] = e[i].val; fa[y][0] = x; Dfs(y); }}/*另一个地方的最大可能不如这里的次大*/void ST(){ for(int j=1;j<=18;j++) for(int i=1;i<=n;i++) if(fa[i][j-1]) { fa[i][j] = fa[fa[i][j-1]][j-1]; int M1 = Max[i][j-1] , M2 = Max[fa[i][j-1]][j-1]; int S1 = sec[i][j-1] , S2 = sec[fa[i][j-1]][j-1]; if(M1 == M2) sec[i][j] = min(S1 , S2); else if(M1 > M2) sec[i][j] = max(S1 , M2); else sec[i][j] = max(S2 , M1); Max[i][j] = max(M1 , M2); }}inline void update(long long a, long long b){ if (a > maxx1) { maxx2 = maxx1; maxx1 = a; if (b > maxx2) maxx2 = b; } else if (a > maxx2 && a != maxx1) maxx2 = a;}void LCA(int a , int b){ if(dep[a] < dep[b]) swap(a , b); for(int i=18;i>=0;i--) if(dep[a] - (1<<i) >= dep[b]) { update(Max[a][i] , sec[a][i]); a = fa[a][i]; } if(a == b) return; for(int i=18;i>=0;i--) if(fa[a][i] != fa[b][i]) { update(Max[a][i] , sec[a][i]); update(Max[b][i] , sec[b][i]); a = fa[a][i] , b = fa[b][i]; } update(Max[a][0] , sec[a][0]); update(Max[b][0] , sec[b][0]);}void Kruscal(int k = 0){ for(int i=1;i<=n;i++) prt[i] = i; sort(edge+1,edge+1+m); for(int i=1;i<=m;i++) { int f1 = Getfather(edge[i].a) , f2 = Getfather(edge[i].b); if(f1 != f2) { prt[f2] = f1; vst[i] = true; Ans += edge[i].c; Addstar(edge[i].a , edge[i].b , edge[i].c); Addstar(edge[i].b , edge[i].a , edge[i].c); if(++k == n-1) break; } }}_int main(){ scanf("%lld %lld",&n,&m); for(int i=1,x,y,z;i<=m;i++) { scanf("%lld %lld %lld",&x,&y,&z); edge[i] = (E) {x , y , z}; } Kruscal(); Dfs(1); ST(); for(int i=1;i<=m;i++) if(!vst[i]) { maxx1 = maxx2 = -1; LCA(edge[i].a , edge[i].b); int t1 = Ans + edge[i].c - maxx1; if(t1 > Ans) Ans_second = min(Ans_second , t1); int t2 = Ans + edge[i].c - maxx2; if(t2 > Ans) Ans_second = min(Ans_second , t2); } cout<<Ans_second; return 0;}
阅读全文
0 0
- [BJOI]2010 严格次小生成树
- 【BZOJ1977】【BJOI2011】严格次小生成树
- BJOI2011 严格次小生成树
- BZOJ1977 (严格)次小生成树
- bzoj1977 严格的次小生成树(LCA倍增)
- BJOI2011 严格次小生成树 解题报告
- 【结论】【非严格次小生成树】NKOJ3855 merlin
- 【C++心路历程29】严格次小生成树
- BZOJ 1977 浅谈严格次小生成树
- POJ 1679 浅谈不严格次小生成树
- [BZOJ1977]严格次小生成树-kruskal+倍增维护
- bzoj 1977 [BeiJing2010组队]次小生成树 Tree [严格的次小生成树]
- 严格次小生成树 并查集和数的综合应用
- 【bzoj1977】【严格次小生成树】倍增维护链上最大次大值
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 树链剖分模板——Luogu P3384
- 线程池的原理及实现
- poj-1724-ROADS(dfs)
- 商品的CRUD(增加删除修改查找)
- redis系列之数据备份与恢复
- [BJOI]2010 严格次小生成树
- DCGAN实验
- java路径以及获取资源文件的方法
- JAVA--网络编程之服务端和客户端
- centos上jdk,mysql,tomcat安装
- hibernate jpa 注解 @Temporal(TemporalType.DATE) 日期注解
- 读写锁ReaderWriterLockSlim
- 第二十一天
- OpenCV Java的配置