[Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)
题目链接:
https://codeforces.com/contest/1051/problem/F
题目大意:
给出一张$n$个点,$m$条边的带权无向图,多次询问,每次给出$u,v$,要求输出$u$到$v$的最短距离
$1<=n<=m<=10^5,m-n<=20$
题解:
显然我们要从$m-n<=20$入手,发现这张图非常的稀疏,所以按照套路我们先随便搞一棵生成树(和kruskal的步骤差不多只是去掉了排序)。
当询问两个点$u,v$的最短距离时我们先只考虑树上的点,显然我们可以预处理出到根节点的距离$O(qlogn)$的搞。
然后考虑非树边,我们称非树边的端点为特殊点,特殊点的个数小于等于40,显然不在树上的最短路径肯定至少经过一个特殊点,所以我们对每个特殊点跑一次dijkstra,然后每次再枚举一下特殊点更新答案即可
- #include<algorithm>
- #include<cstring>
- #include<cstdio>
- #include<iostream>
- #include<vector>
- #include<set>
- #include<queue>
- using namespace std;
- typedef long long ll;
- const int N=2e5+;
- const ll inf=1e17;
- int n,m,tot,k;
- int u[N],v[N],tmp[N],fa[N][],f[N],head[N],d[N];
- ll dd[][N],dep[N],w[N];
- struct EDGE
- {
- int to,nxt;ll w;
- }edge[N<<];
- struct NODE
- {
- int to;ll w;
- };
- vector <NODE> g[N];
- set <int> p;
- struct node
- {
- int now;ll dis;
- };
- bool operator < (node x,node y) {return x.dis>y.dis;}
- inline ll read()
- {
- char ch=getchar();
- ll s=,f=;
- while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
- while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
- return s*f;
- }
- int find(int x)
- {
- if (x!=f[x]) f[x]=find(f[x]);
- return f[x];
- }
- void add(int x,int y,ll w)
- {
- edge[++tot]=(EDGE){y,head[x],w};
- head[x]=tot;
- }
- void dij(int s)
- {
- ++k;
- for (int i=;i<=n;i++) dd[k][i]=inf;
- dd[k][s]=;
- priority_queue <node> q;
- q.push((node){s,});
- while (!q.empty())
- {
- node e=q.top();q.pop();
- int now=e.now;
- if (dd[k][now]!=e.dis) continue;
- for (int i=;i<g[now].size();i++)
- {
- int y=g[now][i].to;
- if (dd[k][y]>dd[k][now]+g[now][i].w)
- {
- dd[k][y]=dd[k][now]+g[now][i].w;
- q.push((node){y,dd[k][y]});
- }
- }
- }
- }
- void dfs(int x,int pre)
- {
- for (int i=;i<=;i++)
- {
- if (d[x]<(<<i)) break;
- fa[x][i]=fa[fa[x][i-]][i-];
- }
- for (int i=head[x];i;i=edge[i].nxt)
- {
- int y=edge[i].to;
- if (y==pre) continue;
- fa[y][]=x;
- dep[y]=dep[x]+edge[i].w;
- d[y]=d[x]+;
- dfs(y,x);
- }
- }
- int lca(int x,int y)
- {
- if (d[x]<d[y]) swap(x,y);
- for (int i=;i>=;i--) if (d[fa[x][i]]>=d[y]) x=fa[x][i];
- if (x==y) return x;
- for (int i=;i>=;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
- return fa[x][];
- }
- int main()
- {
- n=read();m=read();
- for (int i=;i<=m;i++)
- {
- u[i]=read();v[i]=read();w[i]=read();
- g[u[i]].push_back((NODE){v[i],w[i]});
- g[v[i]].push_back((NODE){u[i],w[i]});
- }
- for (int i=;i<=n;i++) f[i]=i;
- for (int i=;i<=m;i++)
- {
- int U=find(u[i]),V=find(v[i]);
- if (U!=V)
- {
- f[U]=V;
- tmp[i]=;
- }
- }
- for (int i=;i<=m;i++)
- {
- if (tmp[i]) {add(u[i],v[i],w[i]);add(v[i],u[i],w[i]);}//printf("qq%d %d\n",u[i],v[i]);
- else p.insert(u[i]),p.insert(v[i]);
- }
- for (set<int>::iterator it=p.begin();it!=p.end();it++) dij((*it));
- d[]=-;dfs(,-);
- //printf("dd%d\n",fa[2][0]);
- int q=read();
- while (q--)
- {
- int x=read(),y=read();
- int LCA=lca(x,y);
- //printf("LL%d\n",LCA);
- ll mi=dep[x]+dep[y]-*dep[LCA];
- //printf("LL%lld\n",mi);
- for (int i=;i<=k;i++)
- {
- mi=min(mi,dd[i][x]+dd[i][y]);
- }
- printf("%lld\n",mi);
- }
- return ;
- }
[Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)的更多相关文章
- codeforces 1051F The Shortest Statement
题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...
- Codeforces.1051F.The Shortest Statement(最短路Dijkstra)
题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...
- 2018.09.24 codeforces 1051F. The Shortest Statement(dijkstra+lca)
传送门 这真是一道一言难尽的题. 首先比赛的时候居然没想出来正解. 其次赛后调试一直调不出来最后发现是depth传错了. 其实这是一道简单题啊. 对于树边直接lca求距离. 由于非树边最多21条. 因 ...
- Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement
1051E. Vasya and Big Integers 题意 给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l, ...
- Codeforces Educational Round 92 赛后解题报告(A-G)
Codeforces Educational Round 92 赛后解题报告 惨 huayucaiji 惨 A. LCM Problem 赛前:A题嘛,总归简单的咯 赛后:A题这种**题居然想了20m ...
- Codeforces Round #382 (Div. 2) 解题报告
CF一如既往在深夜举行,我也一如既往在周三上午的C++课上进行了virtual participation.这次div2的题目除了E题都水的一塌糊涂,参赛时的E题最后也没有几个参赛者AC,排名又成为了 ...
- codeforces 476C.Dreamoon and Sums 解题报告
题目链接:http://codeforces.com/problemset/problem/476/C 题目意思:给出两个数:a 和 b,要求算出 (x/b) / (x%b) == k,其中 k 的取 ...
- codeforces 501C. Misha and Forest 解题报告
题目链接:http://codeforces.com/problemset/problem/501/C 题目意思:有 n 个点,编号为 0 - n-1.给出 n 个点的度数(即有多少个点跟它有边相连) ...
- codeforces 507B. Amr and Pins 解题报告
题目链接:http://codeforces.com/problemset/problem/507/B 题目意思:给出圆的半径,以及圆心坐标和最终圆心要到达的坐标位置.问最少步数是多少.移动见下图.( ...
随机推荐
- Centos上JDK的安装搭建
一.下载 yum search java|grep jdk //查找所有jdk版本 二.选择安装1.8 yum install java-1.8.0-openjdk-src-debug.x86_64 ...
- CentOS 安装 PHP 扩展
下载地址:https://pecl.php.net/package/redis 上传目录:/usr/local/src //安装依赖 yum install php-devel -y //进入安装包目 ...
- JSON是什么?为JavaScript准备的数据格式
JSON是什么?为JavaScript准备的数据格式 还不了解JSON是什么?看了下面这篇文章,您对JSON是什么应该能够有了一个比较清晰的概念. JSON 即 JavaScript. Object ...
- Stack Overflow大揭密:哪一种程序员工资最高?
Stackoverflow在程序员之间可以說是无人不知无人不晓,甚至常有人开玩笑说:“如果stackoverflow倒闭了,全世界代码的产出率将下降一半以上”或许听起来有点夸张,但是不难想像这个网站在 ...
- IOS - [UIDevice currentDevice] name/model/localizedMode/systemName/systemVersion...../userInterfaceIdiom
+ (UIDevice *)currentDevice; @property(nonatomic,readonly,retain) NSString *name; // ...
- [BZOJ3438][洛谷P1361]小M的作物
题目大意:有A.B两个集合和n个物品,每个物品只能放在一个集合里.每个物品放在不同集合内能获得不同价值.有一些物品,如果它们同时放在一个集合内,则会产生新的价值(A和B中都有且不一定相同(c1和c2) ...
- js 对象的创建方式和对象的区别
js一个有三种方法创建对象,这里做一个总结. 1.对象直接量 所谓对象直接量,可以看做是一副映射表,这个方法也是最直接的一个方法,个人比较建议, 1 2 3 4 5 6 7 8 9 10 11 12 ...
- RabbitMQ学习总结(3)——入门实例教程详解
一.起航 本章节,柯南君将从几个层面,用官网例子讲解一下RabbitMQ的实操经典程序案例,让大家重新回到经典"Hello world!"(The simplest thing t ...
- 2015 Multi-University Training Contest 3 hdu 5324 Boring Class
Boring Class Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- javascript-js常用插件集合
area.js 中国地区分级的js代码 Scripts/crypto.js CryptoJS (crypto.js) 为 JavaScript 提供了各种各样的加密算法 ...