正题

题目链接:https://www.ybtoj.com.cn/contest/114/problem/1


题目大意

给出\(n\)个点\(m\)条边的一张无向图,对于每个点\(i\)求不经过\(i\sim 1\)的最短路的第一条边的情况下\(i\)到\(1\)的最短路

数据保证这条边唯一

\(n\in[1,10^5],m\in[1,2\times 10^5],c\in[1,10^3]\)


解题思路

因为保证的那个东西,所以图的最短路树真的是一棵树了,所以先跑出最短路树考虑在最短路树上面搞。

然后题目限制了我们不能从树上的祖先那条边过来,这样就分为了两种情况。一种是从该点的子树外面连过来的边,另一种是从子树中走上来的边。第二种很麻烦,因为子树的最短路是用该节点的最短路扩展的,所以不能直接使用。

考虑一条非树边\((x,y)\),这条边会扩展一条\(dis_y+w\)到\(x\)的路径。(\(dis_x\)表示\(1\sim x\)的最短路)。

并且这条边可以使用到\(LCA(x,y)\)处,此时\(x\)的祖先们都不包含\(y\)在子树内,可以直接用\(y\)的子树扩展。

所以可以维护一个左偏树,每次合并两个儿子的信息,如果堆顶的边需要被删除就删除。需要写一个\(lazy\)标记来修改整棵树

时间复杂度\(O(n\log n)\)


code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<queue>
  5. #include<vector>
  6. #define mp(x,y) make_pair(x,y)
  7. using namespace std;
  8. const int N=4e5+10;
  9. struct point{
  10. int val,x,y;
  11. point(int v=0,int xx=0,int yy=0)
  12. {val=v;x=xx;y=yy;return;}
  13. };
  14. bool operator<(point x,point y)
  15. {return x.val<y.val;}
  16. struct Heap{
  17. point val[N];
  18. int t[N][2],lazy[N],dis[N];
  19. void Downdata(int x){
  20. if(!lazy[x])return;
  21. int ls=t[x][0],rs=t[x][1];
  22. lazy[ls]+=lazy[x];lazy[rs]+=lazy[x];
  23. val[ls].val+=lazy[x];val[rs].val+=lazy[x];
  24. lazy[x]=0;return;
  25. }
  26. int Merge(int x,int y){
  27. Downdata(x);Downdata(y);
  28. if(!x||!y)return x+y;
  29. if(val[y]<val[x])swap(x,y);
  30. int &ls=t[x][0],&rs=t[x][1];
  31. rs=Merge(rs,y);
  32. if(dis[rs]>dis[ls])swap(ls,rs);
  33. dis[x]=dis[rs]+1;return x;
  34. }
  35. int Del(int x){
  36. int &ls=t[x][0],&rs=t[x][1];val[x]=0;
  37. return Merge(ls,rs);
  38. }
  39. }T;
  40. struct node{
  41. int to,next,w;
  42. }a[N];
  43. int n,m,tot,cnt,num,ls[N],f[N];
  44. int rfn[N],p[N],ans[N];
  45. bool v[N];vector<int> G[N];
  46. priority_queue<pair<int,int> >q;
  47. void addl(int x,int y,int w){
  48. a[++tot].to=y;
  49. a[tot].next=ls[x];
  50. ls[x]=tot;a[tot].w=w;
  51. return;
  52. }
  53. void dij(){
  54. memset(f,0x3f,sizeof(f));
  55. q.push(mp(0,1));f[1]=0;
  56. while(!q.empty()){
  57. int x=q.top().second;q.pop();
  58. if(v[x])continue;v[x]=1;
  59. for(int i=ls[x];i;i=a[i].next){
  60. int y=a[i].to;
  61. if(f[x]+a[i].w<f[y]){
  62. f[y]=f[x]+a[i].w;
  63. q.push(mp(-f[y],y));
  64. }
  65. }
  66. }
  67. return;
  68. }
  69. void dfs(int x){
  70. rfn[x]=++cnt;
  71. for(int i=0;i<G[x].size();i++){
  72. int y=G[x][i];dfs(y);
  73. T.val[p[y]].val+=f[y]-f[x];
  74. T.lazy[p[y]]+=f[y]-f[x];
  75. p[x]=T.Merge(p[x],p[y]);
  76. }
  77. for(int i=ls[x];i;i=a[i].next){
  78. int y=a[i].to;
  79. if(f[x]+a[i].w==f[y])continue;
  80. if(f[y]+a[i].w==f[x])continue;
  81. T.val[++num]=point(f[y]+a[i].w,x,y);
  82. p[x]=T.Merge(p[x],num);
  83. }
  84. while(1){
  85. if(!p[x]){ans[x]=-1;break;}
  86. point w=T.val[p[x]];
  87. if(rfn[w.y]>=rfn[x])
  88. {p[x]=T.Del(p[x]);continue;}
  89. ans[x]=w.val;break;
  90. }
  91. return;
  92. }
  93. int main()
  94. {
  95. freopen("pal.in","r",stdin);
  96. freopen("pal.out","w",stdout);
  97. scanf("%d%d",&n,&m);
  98. for(int i=1;i<=m;i++){
  99. int x,y,w;
  100. scanf("%d%d%d",&x,&y,&w);
  101. addl(x,y,w);addl(y,x,w);
  102. }
  103. dij();
  104. for(int x=1;x<=n;x++)
  105. for(int i=ls[x];i;i=a[i].next){
  106. int y=a[i].to;
  107. if(f[x]+a[i].w==f[y])
  108. G[x].push_back(y);
  109. }
  110. dfs(1);
  111. for(int i=2;i<=n;i++)
  112. if(!ans[i])puts("-1");
  113. else printf("%d\n",ans[i]);
  114. return 0;
  115. }

YbtOJ#631-次短路径【左偏树,最短路】的更多相关文章

  1. 左偏树(Leftist Heap/Tree)简介及代码

    左偏树是一种常用的优先队列(堆)结构.与二叉堆相比,左偏树可以高效的实现两个堆的合并操作. 左偏树实现方便,编程复杂度低,而且有着不俗的效率表现. 它的一个常见应用就是与并查集结合使用.利用并查集确定 ...

  2. 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)

    1367: [Baltic2004]sequence Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Ou ...

  3. 『左偏树 Leftist Tree』

    新增一道例题 左偏树 Leftist Tree 这是一个由堆(优先队列)推广而来的神奇数据结构,我们先来了解一下它. 简单的来说,左偏树可以实现一般堆的所有功能,如查询最值,删除堆顶元素,加入新元素等 ...

  4. 洛谷.3273.[SCOI2011]棘手的操作(左偏树)

    题目链接 还是80分,不是很懂. /* 七个操作(用左偏树)(t2表示第二棵子树): 1.合并:直接合并(需要将一个t2中原有的根节点删掉) 2.单点加:把这个点从它的堆里删了,加了再插入回去(有负数 ...

  5. HDU 1512 Monkey King(左偏树模板题)

    http://acm.hdu.edu.cn/showproblem.php?pid=1512 题意: 有n只猴子,每只猴子一开始有个力量值,并且互相不认识,现有每次有两只猴子要决斗,如果认识,就不打了 ...

  6. luogu3261 懒惰左偏树 [JLOI2015]城池攻占

    目录 题目 思路 错误&&反思 代码 题目 luogu 原来左偏树真的能懒惰下放 那这篇博客应该要咕咕了 一开始我按照那篇博客想了一下,感觉emm,还是瞄了一眼看到了pushdown ...

  7. 1455: 罗马游戏[左偏树or可并堆]

    1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1861  Solved: 798[Submit][Status][Discuss] ...

  8. 洛谷 - P1552 - 派遣 - 左偏树 - 并查集

    首先把这个树建出来,然后每一次操作,只能选中一棵子树.对于树根,他的领导力水平是确定的,然后他更新答案的情况就是把他子树内薪水最少的若干个弄出来. 问题在于怎么知道一棵子树内薪水最少的若干个分别是谁. ...

  9. 洛谷 - P3377 - 【模板】左偏树(可并堆) - 左偏树 - 并查集

    https://www.luogu.org/problemnew/show/P3377 左偏树+并查集 左偏树维护两个可合并的堆,并查集维护两个堆元素合并后可以找到正确的树根. 关键点在于删除一个堆的 ...

随机推荐

  1. Data-truncation--Incorrect-string-value

    修改表中,format_content 字段的字符集为utf8mb4 alter table 表名 modify column format_content longtext character se ...

  2. 【mysql】explain性能分析

    1. explain的概念 使用EXPLAIN 关键字可以模拟优化器执行SQL 查询语句,从而知道MySQL 是如何处理你的SQL 语句的.分析你的查询语句或是表结构的性能瓶颈. 用法: Explai ...

  3. C# wpf中DataGrid 支持汇总行

    最近有一个需求,需要汇总金额,份额等字段.我们使用的是原生的WPF控件,自己开发了一套Template.而没有使用比较成熟的第三方控件.所以这个功能得自己开发.并且要做成控件层次的功能. 当然也可以这 ...

  4. Json 文件 : 出现 Expected value at 1:0 问题的解决

    只要找一个json在线解析,验证你的json文件格式的正确性,错误可以忽略. 如要消除红叉,关闭Json Validation即可,如下操作:

  5. C# 读取保存xml文件

    直接读取xml文件中的内容 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(result); XmlNode root = xmlDoc. ...

  6. 【SOE】 ArcGIS Server对象扩展(SOE)开发注意事项

    ArcGIS  Server对象扩展(SOE)开发注意事项 1.SOE介绍 在ArcGIS 10.1中ArcGIS Server不在支持DCOM方式的连接,这也就意味着我们不能通过本地方式的连接使用A ...

  7. shiro(二)

    public class AuthorizerTest { @Test public void testIsPermitted() { login("classpath:shiro-auth ...

  8. ORB_SLAM2 闭环检测段错误

    问题描述: Ubuntu14.04运行正常.Ubuntu 16.04下运行时,检测到闭环后有时会段错误,定位发现断错误出现在CorrectLoop()的红色代码处 void LoopClosing:: ...

  9. nios eclipse提示LED_PIO_BASE没有声明,怎么回事?

    这是因为名字不一致引起的比如,在生成SOPC系统时,双击PIO(Parallel I/O)(在Avalon Modules -> Other 下),为系统添加输出接口,你没有把该组件改名成LED ...

  10. Spring(二)——IOC

    一.入门 1.案例 1 public class Student { 2 3 private String name; 4 5 public Student() { 6 System.out.prin ...