博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【最小生成树+LCA】Imperial roads
阅读量:6165 次
发布时间:2019-06-21

本文共 2863 字,大约阅读时间需要 9 分钟。

I

先跑一遍最小生成树,把经过的边和答案记录下来

对于每个询问的边,显然如果处于MST中,答案不变
如果不在MST中,假设这条边连上了,那么就会和原本的MST形成环,删除这个环中权值最大的边就是答案
处理的时候,可以用LCA维护MST:给出边的两个节点u、v,那么u和v的LCA路径上的最大值边就是环中权值最大的边

代码:

#include 
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;const int MAX_V = 100005;const int MAX_E = 200005;const int MAX_N = 100005;struct LCA_Online { int N, M, E, root, in[MAX_N], head[MAX_N]; int f[MAX_N][30], c[MAX_N][30], depth[MAX_N]; struct Edge { int to, next, cost; } es[MAX_N << 2]; void addEdge(int u, int v, int w) { es[E].to = v; es[E].next = head[u]; es[E].cost = w; head[u] = E++; in[v]++; } void init(int N) { this->N = N; this->M = floor(log2(double(N))); this->E = 0; this->root = 0; memset(head, -1, sizeof head); memset(f, 0, sizeof f); memset(c, 0, sizeof c); memset(in, 0, sizeof in); } void dfs(int u) { for (int j = 1; j <= M; j++) { f[u][j] = f[f[u][j - 1]][j - 1]; c[u][j] = max(c[u][j - 1], c[f[u][j - 1]][j - 1]); } for (int i = head[u]; ~i; i = es[i].next) { int v = es[i].to; int w = es[i].cost; if (v != f[u][0]) { depth[v] = depth[u] + 1; f[v][0] = u; c[v][0] = w; dfs(v); } } } void run() { dfs(1); } int LCA(int u, int v) { if (depth[u] < depth[v]) { swap(u, v); } int res = 0; int d = depth[u] - depth[v]; for (int i = 0; i <= M; i++) { if ((1 << i) & d) { res = max(res, c[u][i]); u = f[u][i]; } } if (u == v) { return res; } for (int i = M; i >= 0; i--) { if (f[u][i] != f[v][i]) { res = max(res, max(c[u][i], c[v][i])); u = f[u][i]; v = f[v][i]; } } return max(res, max(c[u][0], c[v][0])); }} lca;struct Kruskal { struct Edge { int from, to, cost; bool operator< (const Edge& e) const { return cost < e.cost; } } es[MAX_E]; int V, E, p[MAX_V]; void init(int V) { this->V = V; this->E = 0; for (int i = 0; i < V; i++) { p[i] = i; } } void addEdge(int u, int v, int w) { es[E].from = u; es[E].to = v; es[E].cost = w; E++; } int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); } void unite(int x, int y) { p[find(y)] = find(x); } ll kruskal() { ll sum = 0; sort(es, es + E); for (int i = 0; i < E; i++) { Edge &e = es[i]; if (find(e.from) != find(e.to)) { sum += e.cost; unite(e.from, e.to); lca.addEdge(e.from, e.to, e.cost); lca.addEdge(e.to, e.from, e.cost); } } return sum; }} kru;map
, int> cost;int main() { int N, R, Q; scanf("%d%d", &N, &R); kru.init(N); lca.init(N); for (int i = 0, u, v, w; i < R; i++) { scanf("%d%d%d", &u, &v, &w); if (u > v) { swap(u, v); } cost[make_pair(u, v)] = w; //cost[make_pair(v, u)] = w; kru.addEdge(u, v, w); //kru.addEdge(v, u, w); } ll ans = kru.kruskal(); lca.run(); scanf("%d", &Q); while (Q--) { int u, v; scanf("%d%d", &u, &v); if (u > v) { swap(u, v); } printf("%I64d\n", ans + cost[make_pair(u, v)] - lca.LCA(u, v)); }}

转载于:https://www.cnblogs.com/stolf/p/9576581.html

你可能感兴趣的文章
我的友情链接
查看>>
python迭代器的设计
查看>>
【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍
查看>>
logo语言编程介绍
查看>>
ant安装、环境变量配置及验证
查看>>
小蚂蚁学习数据结构(26)——题目——输出二叉树上值大于x的算法
查看>>
php---header函数的简介
查看>>
我的友情链接
查看>>
Linux 批量创建用户及设置随机密码
查看>>
云智慧:创新思维助酷讯IT运维管理升级
查看>>
Rsync 参数详解
查看>>
MySQL错误代码
查看>>
虚拟linux第一次启动网卡配置过程
查看>>
Bind服务简单应用之一(介绍)
查看>>
Windows To Go,让Windows 8移动起来!
查看>>
这是我的第一篇博文,请大家多多关照!~
查看>>
解决启动WebLogic输入用户名密码问题以及密码重置
查看>>
分布式文件系统FastDFS
查看>>
nginx发布静态目录备忘
查看>>
Windows phone8 基础篇(二) xaml介绍 一
查看>>