题目大意:有一个$n$个点,$m$条边的无向图,玩家走过第$i$条边,血槽中的血会下降$v_i$点,如果不足$v_i$点,这人会当场去世。

这$n$个点中,有若干个是关键点,在这些关键点可以将血槽补满。

现在有$q$组询问,每次问一个玩家的血槽至少需要多大,才能从$x$走到$y$。

保证$x$号点和$y$号点可以把你的血槽补满

数据范围:$n≤10^5$,$m≤2\times 10^5$,$V≤10^9$。

我们考虑如果每个点都能补满血槽的话,我们显然可以对原图求一遍最小生成树,每次我们在这颗树上倍增取最大值即可。

不过这一题非常烦人,只有一部分点是可以的。

我们考虑对每个点i处理出$dist[i]$和$from[i]$。

其中,$from[i]$表示距离$i$号点最近的可以补满$i$号点血槽的点的编号,$dist[i]$表示$i$号点距离$from[i]$的距离。

对于原图中任意一条边$(u,v,w)$,若满足$from[u]!=from[v]$,那么我们就在新图中加入$(from[u],from[v],dist[u]+dist[v]+w)$

然后,我们对新图求一个最小生成树,然后在这棵树上倍增即可。

时间复杂度显然是$O((m+n+q)\log\ n)$的。

  1. #include<bits/stdc++.h>
  2. #define L long long
  3. #define M 200005
  4. #define INF (1LL<<60)
  5. using namespace std;
  6.  
  7. struct edge{L u,v,next;}e[M*]={}; L head[M]={},use=;
  8. void add(L x,L y,L z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
  9. L dist[M]={},from[M]={};
  10. L n,m; L ok[M]={},vis[M]={};char c[M]={};
  11.  
  12. struct node{
  13. L u,bel; L dis;
  14. node(){u=bel=dis=;}
  15. node(L U,L Bel,L Dis){u=U; bel=Bel; dis=Dis;}
  16. friend bool operator <(node a,node b){
  17. return a.dis>b.dis;
  18. }
  19. }; priority_queue<node> q;
  20.  
  21. void dij(){
  22. memset(dist,,sizeof(dist));
  23. for(L i=;i<=n;i++) if(ok[i]) q.push(node(i,i,));
  24. while(!q.empty()){
  25. node U=q.top(); q.pop();
  26. L u=U.u; if(dist[u]!=dist[]) continue;
  27. dist[u]=U.dis;
  28. from[u]=U.bel;
  29. for(L i=head[u];i;i=e[i].next)
  30. if(dist[u]+e[i].v<=dist[e[i].u]){
  31. q.push(node(e[i].u,U.bel,dist[u]+e[i].v));
  32. }
  33. }
  34. }
  35.  
  36. struct edge2{
  37. L u,v;L w;
  38. edge2(){u=v=w=;}
  39. edge2(L U,L V,L W){u=U; v=V; w=W;}
  40. friend bool operator <(edge2 a,edge2 b){return a.w<b.w;}
  41. }p[M*]; L N=;
  42.  
  43. L fa[M]={}; L get(L x){return x==fa[x]?x:fa[x]=get(fa[x]);}
  44.  
  45. L f[M][]={},dep[M]={}; L mx[M][]={};
  46. void dfs(L x,L fa,L F){
  47. f[x][]=fa; dep[x]=dep[fa]+; mx[x][]=F;
  48. for(L i=;i<;i++) f[x][i]=f[f[x][i-]][i-],mx[x][i]=max(mx[x][i-],mx[f[x][i-]][i-]);
  49. for(L i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x,e[i].v);
  50. }
  51. L getlca(L x,L y){
  52. if(dep[x]<dep[y]) swap(x,y); L cha=dep[x]-dep[y];
  53. for(L i=;~i;i--) if((<<i)&cha) x=f[x][i];
  54. for(L i=;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
  55. if(x==y) return x; return f[x][];
  56. }
  57. L jump(L x,L k){
  58. L maxn=;
  59. for(L i=;~i;i--) if((<<i)&k){
  60. maxn=max(maxn,mx[x][i]);
  61. x=f[x][i];
  62. }
  63. return maxn;
  64. }
  65.  
  66. main(){
  67. scanf("%lld%lld",&n,&m);
  68. scanf("%s",c+); for(L i=;i<=n;i++) ok[i]=(c[i]=='');
  69. for(L i=,x,y,z;i<=m;i++) scanf("%lld%lld%lld",&x,&y,&z),add(x,y,z),add(y,x,z);
  70. dij();
  71. for(L x=;x<=n;x++)
  72. for(L i=head[x];i;i=e[i].next) if(i&){
  73. L X=x,Y=e[i].u;
  74. if(from[X]!=from[Y]){
  75. p[++N]=edge2(from[X],from[Y],dist[X]+dist[Y]+e[i].v);
  76. }
  77. }
  78. sort(p+,p+N+);
  79. memset(head,,sizeof(head)); use=; memset(e,,sizeof(e));
  80. for(L i=;i<=n;i++) fa[i]=i;
  81.  
  82. for(L i=;i<=N;i++){
  83. L u=get(p[i].u),v=get(p[i].v);
  84. if(u==v) continue; fa[u]=v;
  85. u=p[i].u; v=p[i].v;
  86. add(u,v,p[i].w); add(v,u,p[i].w);
  87. }
  88. L sta=; for(L i=;i<=n;i++) if(ok[i]) {sta=i; break;}
  89.  
  90. dfs(sta,,);
  91.  
  92. L q; scanf("%lld",&q);
  93. while(q--){
  94. L x,y; scanf("%lld%lld",&x,&y);
  95. L lca=getlca(x,y);
  96. printf("%lld\n",max(jump(x,dep[x]-dep[lca]),jump(y,dep[y]-dep[lca])));
  97. }
  98. }

【xsy1300】 原题的旅行 最短路+倍增的更多相关文章

  1. 2018-南京网络赛icpc-L题(分层最短路)

    题意:给你n个点,m条边的有向带权图,然后你每次可以选<=k条边的边权变成0,问你1到n的最短路: 解题思路:这道题基本上就是原题了呀,bzoj2763(无向图),解法就是拆点跑分层的最短路,比 ...

  2. [CF676C]Vasya and String(尺取法,原题)

    题目链接:http://codeforces.com/contest/676/problem/C 原题题解链接:http://www.cnblogs.com/vincentX/p/5405468.ht ...

  3. (各个公司面试原题)在线做了一套CC++综合測试题,也来測一下你的水平吧(二)

    刚才把最后的10道题又看了下.也发上来吧. 以下给出试题.和我对题目的一些理解 前10道题地址 (各个公司面试原题)在线做了一套CC++综合測试题.也来測一下你的水平吧(一) 11.设已经有A,B,C ...

  4. NOIP2016原题终结测试(2017081801)

    NOIP2016还有几道原题没有写掉,今天就一并布置掉. 答案的问题,有部分会先放到NOIP题解中,是单独发布的. 最后会汇总放在答案中,各位不要急. 还有,后期会有原创题测试,这个不急,反正11月才 ...

  5. #LOJ2564 SDOI2018 原题识别 主席树

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/9057297.html 原题链接: 今天考试考了前天的SDOI考题 天啊我菜爆,只有T2拿了30分 然后考试后半 ...

  6. 2019.3.16 noiac的原题模拟赛

    RT,这太谔谔了,我不承认这是模拟赛 但是虽然是搬了三道题,题目本身也还能看,就这么着吧 (怎么机房里就我一道原题都没做过啊 T1 CF24D Broken Robot 比较简单地列出式子之后,我们发 ...

  7. 浅谈《剑指offer》原题:不使用条件、循环语句求1+2+……+n

    转载自:浅谈<剑指offer>原题:求1+2+--+n 如侵犯您的版权,请联系:windeal12@qq.com <剑指offer>上的一道原题,求1+2+--+n,要求不能使 ...

  8. P1048 采药(洛谷,动态规划递推,01背包原题)

    题目直接放链接 P1048 采药 这题只是01背包+背景故事而已 原题来的 PS:我写了一篇很详细的01背包说明,如果下面ac代码有看不懂的地方可以去看看 对01背包的分析与理解(图文) 下面上ac代 ...

  9. NOIP原题 斗地主(20190804)

    题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关 系根据牌的数码表示如下:3<4&l ...

随机推荐

  1. CentOS7双网卡绑定配置

    step1:创建绑定文件 [root@node-1 ~]# vi /etc/sysconfig/network-scripts/ifcfg-bond0 TYPE="bond"BOO ...

  2. Django跨域(前端跨域)

    前情回顾 在说今天的问题之前先来回顾一下有关Ajax的相关内容 Ajax的优缺点 AJAX使用Javascript技术向服务器发送异步请求: AJAX无须刷新整个页面: 因为服务器响应内容不再是整个页 ...

  3. 杨其菊201771010134《面向对象程序设计(java)》第四周学习总结

    <面向对象程序设计(java)> 第四周学习总结 第一部分:理论知识 1.类与对象 a.类(class)是构造对象的模板或蓝图.由类构造对象的过程称为创建类的实例: java中类声明的格式 ...

  4. Spring MVC 的 Converter 和 Formatter

    Converter 和 Formatter 都可用于将一种对象类型转换成另一种对象类型. Converter 是通用元件,可以将一种类型转换成另一种类型,可以在应用程序中的任意层中使用: Format ...

  5. 孤岛营救问题 (BFS+状压)

    https://loj.ac/problem/6121 BFS + 状压 写过就好想,注意细节debug #include <bits/stdc++.h> #define read rea ...

  6. 2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)

    传送门 题意:支持单点修改,维护子树里的最大连通子块和. 思路: 扯皮: bzojbzojbzoj卡常差评. 网上的题解大多用了跟什么最大子段和一样的转移方法. 但是我们实际上是可以用矩阵转移的传统d ...

  7. (PMP)第9章-----项目资源管理

    9.1 规划资源管理 数据表现: 1.层级型(高层次的角色):工作分解结构,组织分解结构,资源分解结构 2.责任分配矩阵:RAM,RACI,执行,负责,咨询,知情(只有一个A) 3.文本型(记录详细职 ...

  8. Android Studio导入项目一直卡在Building gradle project info的解决方案

    出现了一个很神奇的现象,Android Studio导入其它项目均正常,但是导入某个项目(两天前还正常打开的项目)却一直卡在Building gradle project info 尝试了重启Andr ...

  9. Android-Java-静态变量与静态方法&普通变量与普通方法(内存图 完整版)

    描述Student对象: package android.java.oop12; // 描述Student对象实体 public class Student { private String name ...

  10. rand_1tom 产生 rand_1ton

    给定一个等概率随机产生1~M的随机函数rand1ToM如下: public int rand1ToM(int m) { return (int) (Math.random() * m) + 1; } ...