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

题意:求严格次小生成树


我为什么要单独发这篇呢

因为愚蠢的我不停换写法最后发现是因为没开long long所以wa掉的

很简单,次小生成树是由mst换一条边得到的

就是枚举非树边,加入后会形成一个环,求环上的最大值和严格次大值与这条非树边换一换

用倍增可以做到O(mn)-->O(mlogn)

我写了两种求lca时同时求路径上最大值/次大值的做法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int N = 1e5+5, M = 3e5+5;int n, m;
struct edge {int v, ne, w;} e[M<<2];
int cnt, h[N];
inline void ins(int u, int v, int w) {e[++cnt] = (edge) {v, h[u], w}; h[u] = cnt;e[++cnt] = (edge) {u, h[v], w}; h[v] = cnt;
}struct meow {int u, v, w;bool operator < (const meow &r) const {return w < r.w;}
} a[M];bool mark[M];
namespace mst {int fa[N];int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}ll kruskal() {for(int i=1; i<=n; i++) fa[i] = i;sort(a+1, a+1+m);int cnt = 0;ll ans = 0;for(int i=1; i<=m; i++) {int x = find(a[i].u), y = find(a[i].v);if(x != y) { //printf("use (%d, %d) %d\n", a[i].u, a[i].v, a[i].w);fa[y] = x, ans += a[i].w, mark[i] = 1;ins(a[i].u, a[i].v, a[i].w);if(++cnt == n-1) break;}}return ans;}
}int deep[N], fa[N][20], vis[N];
#define fir first
#define sec second
pair<int, int> val[N][20];
pair<int, int> merge(pair<int, int> a, pair<int, int> b) {pair<int, int> ans;if(a.fir == b.fir) ans.fir = a.fir, ans.sec = max(a.sec, b.sec);else if(a.fir > b.fir) ans.fir = a.fir, ans.sec = max(a.sec, b.fir);else ans.fir = b.fir, ans.sec = max(a.fir, b.sec);/*ans.fir = max(a.fir, b.fir);if(a.fir == b.fir) ans.sec = max(a.sec, b.sec);else {ans.sec = min(a.fir, b.fir);ans.sec = max(ans.sec, max(a.sec, b.sec));}*/return ans;
}
void dfs(int u) { vis[u] = 1;for(int j=1; (1<<j)<=deep[u]; j++) {fa[u][j] = fa[fa[u][j-1]][j-1];val[u][j] = merge(val[u][j-1], val[fa[u][j-1]][j-1]);}for(int i=h[u]; i; i=e[i].ne) {int v = e[i].v;if(vis[v]) continue;deep[v] = deep[u]+1;fa[v][0] = u;val[v][0] = make_pair(e[i].w, -1);dfs(v);}
}pair<int, int> lca(int x, int y) { pair<int, int> ans(-1, -1);if(deep[x] < deep[y]) swap(x, y);int bin = deep[x] - deep[y];for(int j=0; j<=17; j++)if((1<<j) & bin) ans = merge(ans, val[x][j]), x = fa[x][j];if(x == y) return ans;for(int j=17; j>=0; j--)if(fa[x][j] != fa[y][j]) {ans = merge(ans, merge(val[x][j], val[y][j]));x = fa[x][j], y = fa[y][j];}ans = merge(ans, merge(val[x][0], val[y][0]));return ans;
}
int lca2(int x, int y) {if(deep[x] < deep[y]) swap(x, y);int bin = deep[x] - deep[y];for(int j=0; j<=17; j++) if((1<<j) & bin) x = fa[x][j];if(x == y) return x;for(int j=17; j>=0; j--) if(fa[x][j] != fa[y][j]) x = fa[x][j], y = fa[y][j];return fa[x][0];
}pair<int, int> cal(int x, int r) {pair<int, int> ans(-1e9, -1e9);int bin = deep[x] - deep[r];for(int j=0; j<=17; j++)if((1<<j) & bin) ans = merge(ans, val[x][j]), x = fa[x][j];return ans;
}
int main() {freopen("in", "r", stdin);ios::sync_with_stdio(false); cin.tie(); cout.tie();cin >> n >> m;for(int i=1; i<=m; i++) {int u, v, w;cin >> u >> v >> w;a[i] = (meow) {u, v, w};}ll mn = mst::kruskal();dfs(1);int ans = 1e9+7;for(int i=1; i<=m; i++) if(!mark[i]) {int u = a[i].u, v = a[i].v, w = a[i].w;//pair<int, int> t = lca(u, v);//printf("hey (%d, %d) %d         %d %d\n", u, v, w, t.fir, t.sec);int r = lca2(u, v);pair<int, int> t = merge(cal(u, r), cal(v, r));if(w > t.fir) ans = min(ans, w - t.fir);if(w == t.fir) ans = min(ans, w - t.sec);}//printf("look %d %d\n", mn, ans);cout << mn + ans;
}

转载于:https://www.cnblogs.com/candy99/p/9273044.html

BZOJ1977: [BeiJing2010组队]次小生成树 Tree相关推荐

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

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

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

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

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

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

  4. BZOJ 1977: [BeiJing2010组队]次小生成树(Kruskal+树上倍增)

    1977: [BeiJing2010组队] 次小生成树 Tree Time Limit: 10 Sec Memory Limit: 512 MB Description 小 C 最近学了很多最小生成树 ...

  5. (Bzoj1977)次小生成树

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

  6. POJ 1679 - The Unique MST(次小生成树)

    题目链接 https://vjudge.net/problem/POJ-1679 Given a connected undirected graph, tell if its minimum spa ...

  7. POJ1679 Luogu4180 次小生成树

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

  8. 非严格次小生成树+严格次小生成树

    非严格次小生成树+严格次小生成树 非严格次小生成树:首先使用最小生成树算法将最小生成树求出来,将生成树建图,然后用倍增维护树上的最大值. 考虑将所有的非树边一次加入最小生成树,并将新边与最小生成树形成 ...

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

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

最新文章

  1. 站长之家html视频播放,HTML5视频发展状况
  2. FPGA_进阶篇开篇
  3. VTK:PolyData之WarpSurface
  4. DOM4J介绍与代码示例 (强大的xml处理工具)
  5. 二进制_简单了解二进制
  6. win10下mount挂载文件 samba cifs
  7. Julia:Datetime的用法
  8. php js调用摄像头,js如何调用摄像头?js调用摄像头的方法(代码详解)
  9. 《绯雨骑士团》Demo
  10. centos7 安装sogou输入法
  11. 【二级等保】二级等保怎么做?价格怎么样?贵吗?
  12. python pip源配置,pip配置文件存放位置的方法
  13. 东大22春《马克思主义基本原理概论》在线平时作业1百分非答案
  14. 平台电子签章实现方法
  15. Linux系统 ·虚拟机安装· SecureCRT远程连接器
  16. 计算机考研专业课考c语言的大学,【择校必看】十三所计算机专业课只考数据结构的985院校!...
  17. oracle 11g下载_oracle11下载
  18. c语言内部收益率,内部收益率 (C++代码)
  19. 不仅仅是“屠龙之技”-编译器开发者的精神胜利!
  20. 浅谈标签传播算法LPA

热门文章

  1. android消息机制
  2. 【Python学习系列四】Python程序通过hadoop-streaming提交到Hadoop集群执行MapReduce
  3. 【正一专栏】亚冠抽签点评——上港令人期待
  4. Android异步加载
  5. 对python的认识作文500字_对阅读新认识作文500字
  6. Get Started with Service Metrics
  7. 深入理解并发内存模型||JMM与内存屏障||多核并发缓存架构 ||JMM内存模型||volatile 关键字的作用 ||JMM 数据原子操作||JMM缓存不一致的问题
  8. 使用帆软finereport实现跳转的一点心得
  9. java vector arraylist linkedlist用法与区别
  10. JAVA: List用法