【BZOJ1977】【MST】【LCA】[BeiJing2010组队]次小生成树 Tree 题解
来源:互联网 发布:淘宝网中老年女外套 编辑:程序博客网 时间:2024/06/03 18:19
Description
小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值)
Input
第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。
Output
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
Sample Input
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
Sample Output
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 。
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <set>#include <queue>#include <algorithm>#include <vector>#include <cstdlib>#include <cmath>#include <ctime>#include <stack>#define INF 2147483647#define LL long long#define clr(x) memset(x, 0, sizeof x)#define ms(a, x) memset(x, a, sizeof x)#define digit (ch < '0' || ch > '9')#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endifusing namespace std;template <class T> inline void read(T &x) { int flag = 1; x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') flag = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x<<1)+(x<<3)+ch-'0'; ch = getchar(); } x *= flag;}using namespace std;const int maxn = 100001;const int maxm = 300001;int n,m,tot,cnt,mn = INF;LL ans;int f[maxn],head[maxn],deep[maxn],fa[maxn][17],d1[maxn][17],d2[maxn][17];struct data{ int x,y,v; bool sel; } a[maxm];struct edge{ int to,nxt,v; } e[maxn<<1];inline bool cmp(data a, data b) { return a.v < b.v; }inline void add(int u, int v, int w) { e[++cnt].to = v; e[cnt].nxt = head[u]; e[cnt].v = w; head[u] = cnt; }inline void insert(int u,int v,int w) { add(u, v, w); add(v, u, w); }int find(int x) { return x == f[x] ? x : find(f[x]); }void dfs(int x, int f) { for(int i = 1; i <= 16; i++) { if(deep[x] < (1<<i)) break; fa[x][i] = fa[fa[x][i-1]][i-1]; d1[x][i] = max(d1[x][i-1], d1[fa[x][i-1]][i-1]); if(d1[x][i-1] == d1[fa[x][i-1]][i-1]) d2[x][i] = max(d2[x][i-1], d2[fa[x][i-1]][i-1]); else { d2[x][i] = min(d1[x][i-1], d1[fa[x][i-1]][i-1]); d2[x][i] = max(d2[x][i-1], d2[x][i]); d2[x][i] = max(d2[x][i], d2[fa[x][i-1]][i-1]); } } for(int i = head[x]; i; i = e[i].nxt) if(e[i].to != f) { fa[e[i].to][0] = x; d1[e[i].to][0] = e[i].v; deep[e[i].to] = deep[x]+1; dfs(e[i].to, x); }}int lca(int x, int y) { if(deep[x] < deep[y]) swap(x, y); int t = deep[x]-deep[y]; for(int i = 0; i <= 16; i++) if((1<<i)&t) x = fa[x][i]; for(int i = 16; i >= 0; i--) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; return x == y ? x : fa[x][0];}inline void cal(int x, int f, int v) { int mx1 = 0, mx2 = 0, t = deep[x]-deep[f]; for(int i = 0; i <= 16; i++) if(t&(1<<i)) { if(d1[x][i] > mx1) mx2 = mx1, mx1 = d1[x][i]; mx2 = max(mx2, d2[x][i]); x = fa[x][i]; } mn = min(mn, mx1 != v ? v-mx1 : v-mx2);}int main() { read(n); read(m); for(int i = 1; i <= n; i++) f[i] = i; for(int i = 1; i <= m; i++) read(a[i].x), read(a[i].y), read(a[i].v); sort(a+1, a+m+1, cmp); for(int i = 1; i <= m; i++) { int p = find(a[i]. x), q = find(a[i].y); if(p != q) { f[p] = q; ans += a[i].v; a[i].sel = 1; insert(a[i].x, a[i].y, a[i].v); tot++; if(tot == n-1) break; } } dfs(1, 0); for(int i = 1; i <= m; i++) if(!a[i].sel) cal(a[i].x, lca(a[i].x, a[i].y), a[i].v), cal(a[i].y, lca(a[i].x, a[i].y), a[i].v); printf(AUTO, ans+mn); return 0;}
阅读全文
0 0
- 【BZOJ1977】【MST】【LCA】[BeiJing2010组队]次小生成树 Tree 题解
- bzoj1977 [BeiJing2010组队]次小生成树 Tree (lca+倍增)
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree【次小生成树】【LCA】
- [BZOJ1977][Beijing2010组队][LCA][Kruskal]次小生成树
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree Kruskal+倍增LCA
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977 [BeiJing2010组队]次小生成树 Tree
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977: [BeiJing2010组队]次小生成树 Tree 树上倍增
- BZOJ1977 [BeiJing2010组队] [次小生成树 Tree]
- bzoj1977 [BeiJing2010组队]次小生成树 倍增
- [BZOJ1977][BeiJing2010组队]次小生成树 Tree(kruskal+链剖)
- bzoj1977: [BeiJing2010]次小生成树 kruskal+倍增LCA
- bzoj1977 [BeiJing2010]次小生成树 Tree(kruskal+树上倍增)
- BZOJ 1977([BeiJing2010组队]次小生成树 Tree-LCA的位运算)
- 【BZOJ】1977 [BeiJing2010组队]次小生成树 Tree kruskal+LCA
- Java4Android笔记之Java中的循环语句
- 小学期 有吃的!
- setAttribute和setParameter方法的区别
- 数据结构实验之链表九:双向链表
- Modern Chinese education, Not the lack of money, but the idea
- 【BZOJ1977】【MST】【LCA】[BeiJing2010组队]次小生成树 Tree 题解
- Tarjan缩点模板(洛谷P3387)
- 第一篇
- Mysql实现级联更新删除
- HDU 5204 Rikka with sequence 思维.
- html图片占位符插件holder.js
- C语言 数据输入/输出函数
- java学习结构图
- PAT --- 1012. 数字分类 (20)