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 棵子树:⑵若根结点不是叶子结点 ...
随机推荐
- centos7 设置静态ip , 并开机联网
修改 /etc/sysconfig/network-scripts 下的文件 我的是ens32 (不同系统这个文件名字不一样) 内容如下 TYPE=Ethernet PROXY_METHOD=none ...
- Jekyll自动检测代码更新
Jekyll自动检测代码更新 jekyll是一个静态博客生成软件, 我们把代码放在一个仓库里, 只要远程代码更新, 我们就从把它拉到自己的服务器, 然后重新启动jekyll. cd /root/blo ...
- Autofac在.NetCore 下的使用
在工作开发中很多地方都会使用到接口模式开发,这里就会用到依赖注入,.NetCore目前是自带的 ,在 Startup.cs中的 ConfigureServices方法中增加 public void C ...
- MySQL事务和事务隔离级别
1.概述 事务就是对数据库数据进行更改(包括insert.update.delete等)操作的一个执行单元,通常有一条或多条更改语句组成.在同一个事务中的更改操作要么同时成功,要么同时失败. 事务具有 ...
- python 基础(实例1——登陆小游戏)
一个简单的登陆小游戏,输入用户名和密码,如果和user_passwd.txt中内容匹配,则打印“welcome to login...”,如果三次输入错误则将该用户列入黑名单,无法再用该用户名登陆. ...
- react-router-dom下的BrowserRouter和HashRouter
奇思妙想的
- MyBatis之Oracle、Mysql批量插入
Mybatis中Dao层 public interface UsersMapper { public void insertEntitys(List<UserEntity> users); ...
- Android笔记(三十七) 如何停止AsyncTask?
当我们加载一张图片的时候,加载的过程中我们想要取消操作,该怎么办呢?调用Asynctask的 cancel() 方法就可以了,我们看代码: 先看一个例子: MainAciticty.java pack ...
- Java 十大排序算法
目录: 1.冒泡排序(Bubble Sort) 2.选择排序(Selection Sort) 3.插入排序(Insertion Sort) 4.希尔排序(Shell Sort) 5.归并排序(Merg ...
- 通过visual studio制作类库的文档
java的集成开发工具,可以导出jar的文档. visual studio 也可以生成类库的文档,邮件项目属性,生成,输出下,选择XML文档文件.然后生成项目,就会再bin下面生成一个xml文件. 将 ...