CF1051F The Shortest Statement

题目大意:给定一张\(n\)个点\(m\)条有权边的无向联通图,\(q\)次询问两点间的最短路

\(n\le100000\),\(m\le100000\),\(1\le100000\),\(m\)-\(n\le20\).

输入样例#1:

3 3
1 2 3
2 3 1
3 1 5
3
1 2
1 3
2 3

输出样例#1:

3
4
1

输入样例#2:

8 13
1 2 4
2 3 6
3 4 1
4 5 12
5 6 3
6 7 8
7 8 7
1 4 1
1 8 3
2 6 9
2 7 1
4 6 3
6 8 2
8
1 5
1 7
2 3
2 8
3 7
3 4
6 8
7 8

输出样例#2:

7
5
6
7
7
1
2
7


一看到非树边最多只有21条就想到跟非树边有关系

然后做法十分的暴力

就是在图中随便找一棵树

并标记其他的非树边所连接的点

这样的点最多只有42个

所以就暴力处理出这些点到其他点的最短路

然后查询的时候就先查只走树边的距离

然后暴力查询其他非树点到\((u,v)\)的路径长度

因为如果\(dis(u,v)\)的路径比只走树边更短

那么一定经过了非树点

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define int long long
const int M = 100005 ;
using namespace std ;
inline int read() {
    char c = getchar() ; int x = 0 , w = 1 ;
    while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    return x*w ;
}

int n , m ;
int hea[M] , num ;
int fa[M][25] , f[M] , dep[M] , cnt ;
int dis[45][M] ;
bool vis[M] , IsN[M] ;
struct Node { int Id , dis ; };
struct E {
    int Nxt , to , dis ;
} edge[M << 2] ;
inline bool operator < (Node a , Node b) { return a.dis > b.dis ; }
inline void add_edge(int from , int to , int dis) {
    edge[++num].Nxt = hea[from] ; edge[num].to = to ;
    edge[num].dis = dis ; hea[from] = num ;
}
void dye(int u , int father , int depth) {
    vis[u] = true ;
    for(int i = hea[u] ; i ; i = edge[i].Nxt) {
        int v = edge[i].to ;
        if(v == father) continue ;
        if(vis[v]) IsN[u] = IsN[v] = true ;
        else {
            fa[v][0] = u ;  dep[v] = dep[u] + 1 ; f[v] = f[u] + edge[i].dis ;
            dye(v , u , depth + 1) ;
        }
    }
}
inline void ST() {
    for(int j = 1 ; j <= 18 ; j ++)
        for(int i = 1 ; i <= n ; i ++)
            fa[i][j] = fa[fa[i][j - 1]][j - 1] ;
}
inline void dijkstra(int t , int S) {
    memset(vis , false , sizeof(vis)) ;
    memset(dis[t] , 63 , sizeof(dis[t])) ; dis[t][S] = 0 ;
    priority_queue < Node > q ; q.push((Node) { S , 0 }) ;
    while(!q.empty()) {
        int u = q.top().Id ; q.pop() ;
        if(vis[u]) continue ; vis[u] = true ;
        for(int i = hea[u] ; i ; i = edge[i].Nxt) {
            int v = edge[i].to ;
            if(dis[t][v] > dis[t][u] + edge[i].dis) {
                dis[t][v] = dis[t][u] + edge[i].dis ;
                if(!vis[v]) q.push((Node) { v , dis[t][v] }) ;
            }
        }
    }
}
inline int LCA(int u , int v) {
    if(dep[u] < dep[v]) swap(u , v) ;
    for(int i = 18 ; i >= 0 ; i --)
        if(dep[fa[u][i]] >= dep[v])
            u = fa[u][i] ;
    if(u == v) return u ;
    for(int i = 18 ; i >= 0 ; i --)
        if(fa[u][i] != fa[v][i])
            u = fa[u][i] , v = fa[v][i] ;
    return fa[u][0] ;
}
# undef int
int main() {
# define int long long
    n = read() ; m = read() ;
    for(int i = 1 , u , v , w ; i <= m ; i ++) {
        u = read() , v = read() , w = read() ;
        add_edge(u , v , w) ; add_edge(v , u , w) ;
    }
    fa[1][0] = 1 ; dye(1 , 1 , 1) ;  ST() ;
    for(int i = 1 ; i <= n ; i ++) if(IsN[i])
        dijkstra(++cnt , i) ;
    int q = read() , u , v , Ans ;
    while(q -- ) {
        u = read() , v = read() ;
        Ans = f[u] + f[v] - (f[LCA(u , v)] << 1) ;
        for(int i = 1 ; i <= cnt ; i ++) Ans = min(Ans , dis[i][u] + dis[i][v]) ;
        printf("%lld\n",Ans) ;
    }
    return 0 ;
}

原文地址:https://www.cnblogs.com/beretty/p/9688187.html

时间: 2024-10-09 17:25:15

CF1051F The Shortest Statement的相关文章

【题解】Luogu CF1051F The Shortest Statement

原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开始虐题 作为蒟蒻的我只能在一旁出售烤绿鸟和main包,和大家一起吃西瓜 仔细想想,这题的确是很弱智 先随便找一个生成树,这样就能跑lca了 剩下的几条边的端点跑一下SPFA堆优化dij,用于特判,SPFA已经死了 查询先用lca算一下距离,再暴力枚举这40个端点到两点的距离值和(最多) 就这样完了,

The Shortest Statement CodeForces - 1051F(待测试)

#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cma

Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement

题目链接:The Shortest Statement 今天又在群里看到一个同学问$n$个$n$条边,怎么查询两点直接最短路.看来这种题还挺常见的. 为什么最终答案要从42个点的最短路(到$x,y$)之和,还有$x,y$到$LCA(x,y)$的距离里面取呢? 就是如果走非树边,那么一定要走42个点中的一个,不走树边,就是LCA求了. 我写的太蠢了,还写生成树,看大家都是LCA中的dfs直接标记下就行了. 验证了算法的正确,我又试了试把每条非树边只加一个点,也是AC的,其实想了想,确实正确. 1

Python interview - text to JSON &amp; zip &amp; with statement

自己写的小例子,就是把本地的txt文件转换为JSON格式输出. data source 简单的1-10存一个文件, A-J 存一个文件 import json book = 'C:\Python27\\book.txt' date = 'C:\Python27\date.txt' book_list = [] date_list = [] with open(book) as b: book_list = b.read().splitlines() with open(date) as d: d

612. Shortest Distance in a Plane

# Write your MySQL query statement belowSELECT ROUND(MIN(SQRT(POW(p1.x-p2.x,2)+POW(p1.y-p2.y,2))),2) AS shortestFROM point_2d p1LEFT JOIN point_2d p2ON !(P1.x=P2.x AND p1.y=p2.y); 原文地址:https://www.cnblogs.com/yuesi/p/10134934.html

Leetcode solution 243: Shortest Word Distance

Problem Statement Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list. Example: Assume that words = ["practice", "makes", "perfect", "coding", "

Hibernate - HHH000352: Unable to release batch statement

这是hibernate的一个bug,具体看https://hibernate.atlassian.net/browse/HHH-11732?attachmentViewMode=list When using stateless session with jdbc batch size we get an HHH000352: Unable to release batch statement.. error in session.close() after rollback: Code:Con

通过maven test 报org.apache.ibatis.binding.BindingException: Invalid bound statement

背景 直接使用eclipse工具去执行,没有问题,通过testng.xml去执行,没有问题,但通过mvn clean test执行,就报错,提示org.apache.ibatis.binding.BindingException: Invalid bound statement 解决方法 首先先肯定的是:mybatis的配置是没有问题,因为eclipse可以正常执行: 在eclipse中把mapper的xml文件放到src代码目录下是可以一起打包进classes的,而maven去编译的时候不会,

JDBC接口介绍之Statement

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权:凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记. Statement: 1.介绍:对数据库数据一系列的操作依赖于SQL语句,而Statement接口是用来执行SQL语句的,Statement对象需要通过Connection类里面的createStatement()方法进行创建.如下图: 先创建一个连接数据库的类,以后就不用再写这片代码了,直接调用此类里面的方法即可: 创建Statement对象: 2.执行S