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

$n\le100000$,$m\le100000$,$1\le100000$,$m$-$n\le20$.

首先看到$m$-$n\le20$这条限制,我们可以想到是围绕这个20来做这道题。

即如果我们随便在图上找一棵树,有最多21条非树边,连接最多42个顶点

考虑两点$x,y$之间的最短路就是某个点到$x$和$y$的最短路之和

首先对于只走树边的情况,这个点是两点的$LCA$

如果经过非树边,$x$或$y$到枚举的这个点的最短路上的最后一条边一定是非树边(如果都是树边的话完全可以转化到一个连接着非树边的点上去)

然后对于所有连接非树边的点都跑一遍最短路,询问时直接枚举这些点取$min$即可

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<queue>
  5. #include<algorithm>
  6. #define M 200010
  7. #define int long long
  8. using namespace std;
  9. int read()
  10. {
  11. char ch=getchar();int x=;
  12. while(ch>''||ch<'') ch=getchar();
  13. while(ch<=''&&ch>='') x=x*+ch-'',ch=getchar();
  14. return x;
  15. }
  16. struct point{
  17. int to,next,dis;
  18. }e[M<<];
  19. int n,m,num,Q,top;
  20. int q[M],head[M],deep[M],dist[M];
  21. int dis[][M],fa[M][];
  22. bool vis[M];
  23. struct node{int id,dis;};
  24. bool operator < (node a1,node a2) {return a1.dis>a2.dis;}
  25. void add(int from,int to,int dis)
  26. {
  27. e[++num].next=head[from];
  28. e[num].to=to;
  29. e[num].dis=dis;
  30. head[from]=num;
  31. }
  32. void dfs(int x,int f)
  33. {
  34. vis[x]=true; fa[x][]=f;
  35. for(int i=head[x];i;i=e[i].next)
  36. {
  37. int to=e[i].to;
  38. if(to==f) continue;
  39. if(vis[to]) q[++top]=x,q[++top]=to;
  40. else
  41. {
  42. deep[to]=deep[x]+;
  43. dist[to]=dist[x]+e[i].dis;
  44. dfs(to,x);
  45. }
  46. }
  47. }
  48. int lca(int x,int y)
  49. {
  50. if(deep[x]<deep[y]) swap(x,y);
  51. for(int i=;i>=;i--)
  52. if(deep[fa[x][i]]>=deep[y])
  53. x=fa[x][i];
  54. if(x==y) return x;
  55. for(int i=;i>=;i--)
  56. if(fa[x][i]!=fa[y][i])
  57. x=fa[x][i],y=fa[y][i];
  58. return fa[x][];
  59. }
  60. void Dijkstra(int id)
  61. {
  62. memset(dis[id],,sizeof(dis[id]));
  63. memset(vis,false,sizeof(vis));
  64. priority_queue<node>Q;
  65. dis[id][q[id]]=;
  66. Q.push((node){q[id],});
  67. while(!Q.empty())
  68. {
  69. int x=Q.top().id;Q.pop();
  70. if(vis[x]) continue;
  71. vis[x]=true;
  72. for(int i=head[x];i;i=e[i].next)
  73. {
  74. int to=e[i].to;
  75. if(!vis[to]&&dis[id][x]+e[i].dis<dis[id][to])
  76. {
  77. dis[id][to]=dis[id][x]+e[i].dis;
  78. Q.push((node){to,dis[id][to]});
  79. }
  80. }
  81. }
  82. }
  83. #undef int
  84. int main()
  85. {
  86. #define int long long
  87. n=read(); m=read();
  88. for(int i=;i<=m;i++)
  89. {
  90. int a=read(),b=read(),c=read();
  91. add(a,b,c); add(b,a,c);
  92. }
  93. deep[]=;dfs(,);
  94. for(int j=;j<=;j++)
  95. for(int i=;i<=n;i++)
  96. fa[i][j]=fa[fa[i][j-]][j-];
  97. sort(q+,q++top); top=unique(q+,q++top)-q-;
  98. for(int i=;i<=top;i++) Dijkstra(i);
  99. Q=read();
  100. while(Q--)
  101. {
  102. int x=read(),y=read();
  103. int ans=dist[x]+dist[y]-*dist[lca(x,y)];
  104. for(int i=;i<=top;i++) ans=min(ans,dis[i][x]+dis[i][y]);
  105. printf("%lld\n",ans);
  106. }
  107. return ;
  108. }

[CF1051F]The Shortest Statement的更多相关文章

  1. 【题解】Luogu CF1051F The Shortest Statement

    原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开 ...

  2. cf1051F. The Shortest Statement(最短路/dfs树)

    You are given a weighed undirected connected graph, consisting of nn vertices and mm edges. You shou ...

  3. CF1051F The Shortest Statement 题解

    题目 You are given a weighed undirected connected graph, consisting of n vertices and m edges. You sho ...

  4. [CF1051F]The Shortest Statement (LCA+最短路)(给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路)

    题目:给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路 n≤100000,m≤100000,m-n≤20. 首先看到m-n≤20这条限制,我们可以想到是围绕这个20来做这道题. 即如果我们 ...

  5. cf1051F. The Shortest Statement(最短路)

    题意 题目链接 题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$ $n, m, q \leqslant 10^5$ Sol 非常好的一道题. 首先建出一个dfs树. ...

  6. CF1051F The Shortest Statement Dijkstra + 性质分析

    动态询问连通图任意两点间最短路,单次询问. 显然,肯定有一些巧妙地性质(不然你就发明了新的最短路算法了233)有一点很奇怪:边数最多只比点数多 $20$ 个,那么就可以将这个图看作是一个生成树,上面连 ...

  7. codeforces 1051F The Shortest Statement

    题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...

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

    #include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...

  9. Educational Codeforces Round 51 (Rated for Div. 2) F - The Shortest Statement 倍增LCA + 最短路

    F - The Shortest Statement emmm, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...

随机推荐

  1. gdb常见命令(未完,待续)

    // 编译文件时,带参-g > gcc -g test.c // 进入gdb调试界面 > gdb a.out 或者 > gdb > file a.out // 查看文件内容 & ...

  2. protobuf在java应用中通过反射动态创建对象(DynamicMessage)

    ---恢复内容开始--- 最近编写一个游戏用到protobuf数据格式进行前后台传输,苦于protobuf接受客户端的数据时是需要数据类型的如xxx.parseForm(...),这样就要求服务器在接 ...

  3. java讲讲几种常见的排序算法

    java讲讲几种常见的排序算法(一) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 以数组array={6,3,20,8,15,1}为例 冒泡排序 思路:从第0个到 ...

  4. mysql 浏览器submit中文, shell乱码

    w控制变量法. 初始 浏览器submit中文 成功执行 问题仍未解决 执行 SET character_set_database='latin1'; 再执行 SET character_set_res ...

  5. C#日期处理(转) 太忘记了,备忘

    //今天 DateTime.Now.Date.ToShortDateString(); //昨天,就是今天的日期减一 DateTime.Now.AddDays(-1).ToShortDateStrin ...

  6. 隐藏Apache、nginx和PHP的版本号的配置方法

    最近提示说有漏洞,暴露apache.nginx和php的版本号.网上搜了下,整理的方法如下: 首先说apache 在http.conf文件里添加下面两行,默认是没有的 ServerSignature ...

  7. VI乱码, cat 和 more正常

    今天在做一个东西的时候发现,vi乱码,cat,more这个文件汉字显示也正常,查了网上很多东西最后发现按一种说法改对了: 应该是格式化的问题! 比如man手册的文件有一些格式标记,你用man   ,c ...

  8. QT in VS 多语言实现(中英文切换,每个步骤都有截图,只有UTF8才能让Qt语言家正确读取。先qApp->removeTranslator,然后installTranslator,每个类都要写上槽函数RetranslateUI)

    最近项目需要软件具有中英文双语切换功能,而QT又自带此功能,现将实现方式记录下来. 说到中英文切换,少不了要了解QT的内部编码方式.在此就不详述QT编码方式了,具体可参考 彻底弄懂Qt的编码.只需要记 ...

  9. Pandas 如何通过获取双(多)重索引获取指定行DataFrame数据

    图片看不清楚的话,可以右键选择:“在新标签页中打开图片(I)” 参数 df.loc[(a,b),c]中第一个参数元组为索引内容,a为level0索引对应的内容,b为level1索引对应的内容 因为df ...

  10. html table表格列数太多添加横向滚动条

    HTML的table表格的列数如果太多或者某一列的内容太长,就会导致表格td的内容被挤压变形,对后台的使用体验非常不友好.比如下面的情况: 那么如何在表格列数较多的情况下添加横向滚动条?其实很简单,只 ...