cf 1051F 树+图
$des$
给定一张 $n$ 个点 $m$ 条边的带权无向联通图,$q$ 次询问,每次询问 $u_i$ 到 $v_i$ 的最短
路长度。
$n,q <= 10^5, m - n <= 20$
$sol$
首先随便搞一棵生成树,那么会有一些边不在生成树上。
把这些边的端点标记为特殊点。
对于一个询问,如果最短路只经过生成树上的边,就可以直接计算。
否则一定经过了一个特殊点,可以枚举这个特殊点,然后更新答案
$code$
#include <bits/stdc++.h> using namespace std; #define gc getchar()
inline int read() {
int x = ; char c = gc;
while(c < '' || c > '') c = gc;
while(c >= '' && c <= '') x = x * + c - '', c = gc;
return x; } #define LL long long
#define Rep(i, a, b) for(int i = a; i <= b; i ++) const int N = 1e5 + ; int Now;
int cnt, head[N], cnt2, head2[N];
struct Node {
int u, v, w, nxt;
bool used;
} E[N], Gr[N << ], G[N << ]; int n, m;
int Nottree[], tot; int fat[N]; int Get(int x) {
return fat[x] == x ? x : fat[x] = Get(fat[x]);
} void Link(int u, int v, int w) {
G[++ cnt].v = v; G[cnt].w = w; G[cnt].nxt = head[u]; head[u] = cnt;
} void Link_g(int u, int v, int w) {
Gr[++ cnt2].v = v; Gr[cnt2].w = w; Gr[cnt2].nxt = head2[u]; head2[u] = cnt2;
} void Kruskal() {
int js = ;
Rep(i, , m) {
int u = E[i].u, v = E[i].v;
int fau = Get(u), fav = Get(v);
if(fau != fav) {
fat[fau] = fav;
js ++;
Link(u, v, E[i].w);
Link(v, u, E[i].w);
E[i].used = ;
}
if(js == n - ) break;
}
} struct Short {
LL u, dis_;
bool operator < (const Short a) const {
return this-> dis_ > a.dis_;
}
};
LL dis[][N];
bool vis[N];
priority_queue <Short> Q; void Dijkstra(int start) {
Rep(i, , n) dis[Now][i] = 1e18, vis[i] = ;
Q.push((Short) {start, dis[Now][start] = });
while(!Q.empty()) {
Short tp = Q.top();
Q.pop();
if(vis[tp.u]) continue;
vis[tp.u] = ;
for(int i = head2[tp.u]; ~ i; i = Gr[i].nxt) {
int v = Gr[i].v;
if(dis[Now][v] > dis[Now][tp.u] + Gr[i].w) {
dis[Now][v] = dis[Now][tp.u] + Gr[i].w;
Q.push((Short) {v, dis[Now][v]});
}
}
}
} int fa[N], size[N], son[N], topp[N];
LL deep[N]; void Dfs1(int u, int f_, LL dep) {
size[u] = ; fa[u] = f_; deep[u] = dep;
for(int i = head[u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(v == f_) continue;
Dfs1(v, u, dep + G[i].w);
size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
} void Dfs2(int u, int tp) {
topp[u] = tp;
if(!son[u]) return ;
Dfs2(son[u], tp);
for(int i = head[u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(v != fa[u] && v != son[u]) Dfs2(v, v);
}
} inline int Lca(int x, int y) {
int tpx = topp[x], tpy = topp[y];
while(tpx != tpy) {
if(deep[tpx] < deep[tpy]) swap(x, y), swap(tpx, tpy);
x = fa[tpx], tpx = topp[x];
}
if(deep[x] < deep[y]) swap(x, y);
return y;
} int main() {
n = read(), m = read();
Rep(i, , n) head[i] = -, head2[i] = -;
Rep(i, , n) fat[i] = i;
Rep(i, , m) {
int u = read(), v = read(), w = read();
E[i] = (Node) {u, v, w, , };
Link_g(u, v, w), Link_g(v, u, w);
} Kruskal();
Rep(i, , m) if(E[i].used == ) Nottree[++ tot] = E[i].u, Nottree[++ tot] = E[i].v; Rep(i, , tot) {
Now ++;
Dijkstra(Nottree[i]);
} Dfs1(, , );
Dfs2(, ); for(int q = read(); q; q --) {
int u = read(), v = read();
LL Answer = deep[u] + deep[v] - * deep[Lca(u, v)];
Rep(i, , tot) {
Answer = min(Answer, dis[i][u] + dis[i][v]);
}
cout << Answer << '\n';
} return ;
}
cf 1051F 树+图的更多相关文章
- CF 1051F
题意:给定一张n个点,m条边的无向联通图,其中m-n<=20,共q次询问,每次询问求给定两点u,v间的最短路长度 第一眼看见这题的时候,以为有什么神奇的全图最短路算法,满心欢喜的去翻了题解,发现 ...
- POJ2513(字典树+图的连通性判断)
//用map映射TLE,字典树就AC了#include"cstdio" #include"set" using namespace std; ; ;//26个小 ...
- CF 61E 树状数组+离散化 求逆序数加强版 三个数逆序
http://codeforces.com/problemset/problem/61/E 题意是求 i<j<k && a[i]>a[j]>a[k] 的对数 会 ...
- 树&图 记录
A - Lake Counting POJ - 2386 最最最最最基础的dfs 挂这道题为了提高AC率(糖水不等式 B - Paint it really, really dark gray Cod ...
- DS树+图综合练习--构建邻接表
题目描述 已知一有向图,构建该图对应的邻接表.邻接表包含数组和单链表两种数据结构,其中每个数组元素也是单链表的头结点,数组元素包含两个属性,属性一是顶点编号info,属性二是指针域next指向与它相连 ...
- DS树+图综合练习--二叉树之最大路径
题目描述 给定一颗二叉树的逻辑结构(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构 二叉树的每个结点都有一个权值,从根结点到每个叶子结点将形成一条路径, ...
- DS树+图综合练习--带权路径和
题目描述 计算一棵二叉树的带权路径总和,即求赫夫曼树的带权路径和. 已知一棵二叉树的叶子权值,该二叉树的带权案路径和APL等于叶子权值乘于根节点到叶子的分支数,然后求总和.如下图中,叶子都用大写字母表 ...
- cf 911F 树的直径+贪心
$des$ 给定一棵 n 个节点的树,你可以进行 n ? 1 次操作,每次操作步骤如下:选择 u,v 两个度数为 1 的节点.将 u,v 之间的距离加到 ans 上.将 u 从树上删除.求一个操作序列 ...
- 数据结构 B-树和B+树的应用:数据搜索和数据库索引
B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每个结点至多有m 棵子树:⑵若根结点不是叶子结点 ...
随机推荐
- Jenkins + GitLab + SpringBoot 实现持续集成脚本
Linux脚本 #!/bin/bash jar_name=hq-api.jar cd /usr/local/app/hq-api echo "Stopping SpringBoot Appl ...
- Java 平衡二叉树和AVL
与BST<> 进行对比 import java.util.ArrayList; import java.util.Collections; public class Main { pu ...
- C# vb实现浮雕特效滤镜效果
在.net中,如何简单快捷地实现Photoshop滤镜组中的浮雕效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步 ...
- 湖南师范大学计算机基础课网络教学平台 版本 V2.0(2017.9.18)
湖南师范大学计算机基础课网络教学平台 版本 V2.0(2017.9.18) 开发环境: 开发工具:VS2013,数据库:Sqlserver2012 开发语言:Asp.net MVC5 ,界面UI:jq ...
- angular 8 配置路由
一.生成路由文件 按照惯例,有一个独立模块来配置相关路由,这个模块类的名字叫做AppRoutingModule,位于src/app下的app-routing.module.ts文件中. 使用CLI生成 ...
- MongoDB 4.2.1 安装失败,提示 verify that you have sufficient privileges to start system services 解决
官网下载地址:https://www.mongodb.com/download-center/community 问题: 解决:直接安装在根目录 测试:
- MySQL数据库使用时注意事项
MySQL数据库使用时注意事项 建表的角度上 1.合理安排表关系 2.尽量把固定长度的字段放在前面 3.尽量使用char 代替varchar 4.分表:水平分和垂直分 在使用sql语句的时候 1.尽量 ...
- 在js中把json中的 key去掉双引号的方法
方法一: //数据格式是这样的: var data = '[{"id":30348079,"name":"表1","score&q ...
- Matlab title正确显示下划线
前言 使用matlab中title语句,直接敲下划线无法正确显示. title('MSB_data'); 流程 使用如下语句即可:直接字符串转译 title('MSB_data','Interpret ...
- SQL----EXISTS 关键字
转自:http://blog.sina.com.cn/s/blog_65dbc6df0100mvfx.html 1.EXISTS基本意思 英语解释就是存在,不过他的意思也差不多,相当于存在量词'З'. ...