$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 树+图的更多相关文章

  1. CF 1051F

    题意:给定一张n个点,m条边的无向联通图,其中m-n<=20,共q次询问,每次询问求给定两点u,v间的最短路长度 第一眼看见这题的时候,以为有什么神奇的全图最短路算法,满心欢喜的去翻了题解,发现 ...

  2. POJ2513(字典树+图的连通性判断)

    //用map映射TLE,字典树就AC了#include"cstdio" #include"set" using namespace std; ; ;//26个小 ...

  3. CF 61E 树状数组+离散化 求逆序数加强版 三个数逆序

    http://codeforces.com/problemset/problem/61/E 题意是求 i<j<k && a[i]>a[j]>a[k] 的对数 会 ...

  4. 树&图 记录

    A - Lake Counting POJ - 2386 最最最最最基础的dfs 挂这道题为了提高AC率(糖水不等式 B - Paint it really, really dark gray Cod ...

  5. DS树+图综合练习--构建邻接表

    题目描述 已知一有向图,构建该图对应的邻接表.邻接表包含数组和单链表两种数据结构,其中每个数组元素也是单链表的头结点,数组元素包含两个属性,属性一是顶点编号info,属性二是指针域next指向与它相连 ...

  6. DS树+图综合练习--二叉树之最大路径

    题目描述 给定一颗二叉树的逻辑结构(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构 二叉树的每个结点都有一个权值,从根结点到每个叶子结点将形成一条路径, ...

  7. DS树+图综合练习--带权路径和

    题目描述 计算一棵二叉树的带权路径总和,即求赫夫曼树的带权路径和. 已知一棵二叉树的叶子权值,该二叉树的带权案路径和APL等于叶子权值乘于根节点到叶子的分支数,然后求总和.如下图中,叶子都用大写字母表 ...

  8. cf 911F 树的直径+贪心

    $des$ 给定一棵 n 个节点的树,你可以进行 n ? 1 次操作,每次操作步骤如下:选择 u,v 两个度数为 1 的节点.将 u,v 之间的距离加到 ans 上.将 u 从树上删除.求一个操作序列 ...

  9. 数据结构 B-树和B+树的应用:数据搜索和数据库索引

    B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每个结点至多有m 棵子树:⑵若根结点不是叶子结点 ...

随机推荐

  1. go语言学习---使用os.Args获取简单参数(命令行解析)

    实例1: //main package main import ( "fmt" "os" ) func main() { fmt.Println(os.Args ...

  2. Java 枚举和抽象类添加状态值

    枚举: public enum CourseTypeEnum { VIDEO_COURSE(1,"录制课程"), LIVE_COURSE(2,"直播课程"), ...

  3. redis 安装使用 & SpringBoot Redis配置

    1.安装 https://www.cnblogs.com/dingguofeng/p/8709476.html https://www.runoob.com/redis/redis-keys.html ...

  4. .NET Window服务启动又马上停止,报错IO.FileNotFoundException

    最近公司需要开发一个Window服务推送系统,读取MongoDB写入消息队列,推送到各终端平台 但是在开发完成,最后的部署阶段,选中服务右击启动 看似正常,服务显示已启动(但实质已经被终止,因为Win ...

  5. SQL Server 截取日期部分字符

    select GetDate() --用DateName()就可以获得相应的年.月.日 Select Datename(year,GetDate())+'-'+Datename (month,GetD ...

  6. ASP.NET Core 入门(2)(WebApi接口请求日志 Request和Response)

    以前 .NET Framework WebApi 记录接口访问日志,一般是通过Filter的方式进行拦截,通过重写ActionFilterAttribute的OnActionExecuting实现拦截 ...

  7. 转 如何在调用WCF服务之前弹出一个确认对话框

    自定义InteractiveChannelInitializer(InvocationConfirmationInteractiveChannelInitializer)定义如下.我们在BeginDi ...

  8. springboot笔记08——整合swagger2

    Swagger是什么? Swagger是一个RESTFUL 接口的文档在线自动生成和功能测试的框架.利用swagger2的注解可以快速的在项目中构建Api接口文档,并且提供了测试API的功能. Spr ...

  9. windows cmd下列出当前目录下的所有文件

    使用的命令是dir 如,列出当前目录下的目录及文件名到1.txt: dir /b >1.txt 只列出某类文件 dir *.txt  /b >1.txt

  10. Manjaro 安装笔记

    双系统基本知识 [折腾日记]win10 ,ubuntu双系统安装避坑指南 Windows 下安装 Ubuntu 双系统(更新) rEFInd 总结注意点: 制作U盘启动盘一开始使用的是 Ulrstro ...