题目描述

雪之国度有N座城市,依次编号为1到N,又有M条道路连接了其中的城市,每一条道路都连接了不同的2个城市,任何两座不同的城市之间可能不止一条道路。雪之女王赋予了每一座城市不同的能量,其中第i座城市被赋予的能量为Wi。

如果城市u和v之间有一条道路,那么只要此刻雪之女王的能量不小于|Wu-Wv|,这条道路就是安全的。如果城市u和v之间存在两条没有重复道路的安全路径(其中每一段道路都是安全的),则认为这两座城市之间有着良好的贸易关系。

最近,雪之女王因为情感问题,她的能量产生巨大的波动。为了维持雪之国度的经济贸易,她希望你能帮忙对Q对城市进行调查。对于第j对城市uj和vj,她希望知道在保证这两座城市之间有着良好贸易关系的前提之下,自己最少需要保持多少的能量。

数据范围

对于20%的数据来说,3<=N<=10, 3<=M<=20, 1<=Q<=10

对于另30%的数据来说,Wi=0

对于100%的数据来说,3<=N<=100000, 3<=M<=500000, 1<=Q<=100000, 每一座城市的能量Wi满足0<=Wi<=200000.

=w=

对原树进行最小生成树,一开始所有树边,对剩余的边按权值从小到大进行操作:

对于一条(u,v,w)的边,在最小生成树上(u,v)的这条路径上的所有标记为未修改的边权改为w,并把它们标记为已修改。

所有边都加入了以后,对于每个询问(u,v),都使用LCA求树上路径的最大值即可。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #define ll long long
  7. #define sqr(x) ((x)*(x))
  8. #define ln(x,y) int(log(x)/log(y))
  9. using namespace std;
  10. const char* fin="tour.in";
  11. const char* fout="tour.out";
  12. const int inf=0x7fffffff;
  13. const int maxn=100009,maxm=maxn*2,maxk=17;
  14. int n,m,q,i,j,k;
  15. int a[maxn],b[maxn];
  16. int fi[maxn],la[maxm],ne[maxm],tot;
  17. int fa[maxn][maxk],de[maxn];
  18. void add_line(int a,int b){
  19. tot++;
  20. ne[tot]=fi[a];
  21. la[tot]=b;
  22. fi[a]=tot;
  23. }
  24. void pre(int v,int from){
  25. int i,j,k;
  26. de[v]=de[from]+1;
  27. for (i=1;i<maxk;i++) fa[v][i]=fa[fa[v][i-1]][i-1];
  28. for (k=fi[v];k;k=ne[k])
  29. if (la[k]!=from){
  30. fa[la[k]][0]=v;
  31. pre(la[k],v);
  32. }
  33. }
  34. void up(int &a,const int &i,int &ans){
  35. ans+=1<<i;
  36. a=fa[a][i];
  37. }
  38. int lca(int a,int b){
  39. int i,j,k=0;
  40. if (de[a]<de[b]) swap(a,b);
  41. for (i=maxk-1;i>=0;i--) if (de[fa[a][i]]>de[b]) up(a,i,k);
  42. if (de[a]!=de[b]) up(a,0,k);
  43. for (i=maxk-1;i>=0;i--) if (fa[a][i]!=fa[b][i]) up(a,i,k),up(b,i,k);
  44. if (a!=b) up(a,0,k),up(b,0,k);
  45. return k;
  46. }
  47. struct path{
  48. int x,y,len;
  49. void init(){
  50. x=y=len=0;
  51. }
  52. path(){
  53. init();
  54. }
  55. void get(const int &X,const int &Y,const int &Len){
  56. if (Len>len){
  57. x=X;
  58. y=Y;
  59. len=Len;
  60. }
  61. }
  62. void update(int A,int B);
  63. }li[maxn],Old,Ans,New;
  64. void path::update(int A,int B){
  65. if (A==0 || B==0) return;
  66. int i=lca(A,B);
  67. if (a[A]!=a[B]) Ans.get(A,B,i);
  68. if (i>len) get(A,B,i);
  69. }
  70. path merge(const path &a,const path &b){
  71. path c;
  72. if (a.x==0) return b;
  73. if (b.x==0) return a;
  74. if (a.len>b.len) c.get(a.x,a.y,a.len);
  75. else c.get(b.x,b.y,b.len);
  76. c.update(a.x,b.x);
  77. c.update(a.x,b.y);
  78. c.update(a.y,b.x);
  79. c.update(a.y,b.y);
  80. return c;
  81. }
  82. void dfs(int v,int from){
  83. int i,j,k,co=a[v];
  84. New.init();
  85. New.x=New.y=v;
  86. li[co]=merge(li[co],New);
  87. for (k=fi[v];k;k=ne[k])
  88. if (la[k]!=from) dfs(la[k],v);
  89. }
  90. int main(){
  91. freopen(fin,"r",stdin);
  92. freopen(fout,"w",stdout);
  93. scanf("%d%d%d",&n,&m,&q);
  94. for (i=1;i<=n;i++){
  95. scanf("%d",&a[i]);
  96. }
  97. for (i=1;i<n;i++){
  98. scanf("%d%d",&j,&k);
  99. add_line(j,k);
  100. add_line(k,j);
  101. }
  102. pre(1,0);
  103. dfs(1,0);
  104. for (i=1;i<=q;i++){
  105. scanf("%d",&j);
  106. Old.init();
  107. Ans.init();
  108. b[0]=0;
  109. for (;j;j--){
  110. scanf("%d",&b[++b[0]]);
  111. Old=merge(Old,li[b[b[0]]]);
  112. }
  113. Ans.len++;
  114. if (Ans.len==1) printf("-1\n");
  115. else printf("%d\n",Ans.len);
  116. }
  117. return 0;
  118. }

=o=

我认为这一道题最难点在于想出:最小生成树。

我在比赛时做这一道题,想着对于每一个询问,二分答案后使用边双来判断答案是否合法。

但是这个时间复杂度会是O(q∗log∗n)。

一直想要使用交集优化来优化时间,但是,无法优化。

然后我就懵逼了。


如果我们按顺序加入一些边的话,那么我们就可以保证,加入边之后的答案会最优化。

所以就能得出使用最小生成树这个思路。

【JZOJ4899】【NOIP2016提高A组集训第17场11.16】雪之国度的更多相关文章

  1. 【JZOJ4898】【NOIP2016提高A组集训第17场11.16】人生的价值

    题目描述 NiroBC终于找到了人生的意义,可是她已经老了,在新世界,没有人认识她,她孤独地在病榻上回顾着自己平凡的一生,老泪纵横.NiroBC多么渴望再多活一会儿啊! 突然一个戴着黑色方框眼镜,方脸 ...

  2. 【JZOJ4901】【NOIP2016提高A组集训第18场11.17】矩阵

    题目描述 他是一名普通的农电工,他以一颗无私奉献的爱岗敬业之心,刻苦钻研业务,以娴熟的技术.热情周到的服务赢得了广大客户的尊敬和赞美.他就是老百姓称为"李电"的李春来. 众所周知, ...

  3. 【NOIP2016提高A组集训第4场11.1】平衡的子集

    题目 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 分析 如果暴力枚举每个人被分到哪 ...

  4. 【JZOJ4855】【NOIP2016提高A组集训第6场11.3】荷花池塘

    题目描述 于大夫建造了一个美丽的池塘,用来让自己愉快的玩耍.这个长方形的池子被分割成了M 行 和N 列的正方形格子.池塘中有些地方是可以跳上的荷叶,有些地方是不能放置荷叶也不 能跳上的岩石,其他地方是 ...

  5. 【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集

    题目描述 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 数据范围 40%的数据满足: ...

  6. 【NOIP2016提高A组集训第14场11.12】随机游走

    题目 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己是不 ...

  7. 【NOIP2016提高A组集训第13场11.11】最大匹配

    题目 mhy12345学习了二分图匹配,二分图是一种特殊的图,其中的点可以分到两个集合中,使得相同的集合中的点两两没有连边. 图的"匹配"是指这个图的一个边集,里面的边两两不存在公 ...

  8. 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP

    好久没有写过题解了--现在感觉以前的题解弱爆了,还有这么多访问量-- 没有考虑别人的感受,没有放描述.代码,题解也写得歪歪扭扭. 并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通 ...

  9. 【JZOJ4893】【NOIP2016提高A组集训第15场11.14】过河

    题目描述 数据范围 解法 由于同一个点,同一个圆盘最多只会走一次. 把(i,j)当作一个点,表示第i个点,放第i个圆盘. 那么就可以使用最短路. 时间复杂度为O(n4∗k). 事实上存在冗余圆盘,一个 ...

随机推荐

  1. HZOI2019 B. 那一天她离我而去 最小环

    题目大意:https://www.cnblogs.com/Juve/articles/11219089.html 那一天,我们......行啦,不要帮出题人脑补画面了,我们来正经的题解 我们发现我们可 ...

  2. PHP--封装干净利落的输出dump()函数

    /** * 打印函数 * */ if (! function_exists ( 'dump' )) { function dump($var, $exit = true) { echo '<pr ...

  3. vim之buffer 与 折叠

    常用的折叠命令有: zf zi zo zc zd zf10j从当前行向下10行创建折叠(共11行),zfj创建两行的折叠 常用的还有zf%. 进行多文件编辑时,会涉及到buffer的使用::ls 查看 ...

  4. thinkphp浏览历史功能实现方法

    这篇文章主要介绍了thinkphp浏览历史功能实现方法,可实现浏览器的浏览历史功能,是非常实用的技巧,需要的朋友可以参考下 本文实例讲述了thinkphp浏览历史功能实现方法,分享给大家供大家参考.具 ...

  5. idea使用及其快捷键(Jetbrains很多是通用的)(转)

    Java程序员肯定会使用idea进行开发,因为其非常强大,很好用,而且可以很傻瓜式导入gradle,用来做SSM项目也很简单 学生是可以使用教育邮箱或者上床学生证使用免费的jetbrains全家桶的, ...

  6. hbase Hfile处理原因

    Hile 内部的数据是按key排序好的,但Hfile之间数据并不能保证key的排序,也就是说对于新生成的Hfile,其内部的key并不都比老的Hfile的大,因此每次检索时,都需要在所有的Hfile中 ...

  7. grep与find命令的区别

    grep与find命令的区别:grep搜索的是文本,find搜索的是文件,换句话说就是grep是查找匹配条件的行,find是搜索匹配条件的文件. grep文本搜索/过滤 用法:grep[参数]搜索字符 ...

  8. 四种基本组合博弈POJ1067/HDU1846

    取石子游戏 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 43466   Accepted: 14760 Descripti ...

  9. 字符界面总是显示 login incorrect

    一般来说出现这样的提示,是因为登陆的密码错误,如果密码中有数字,最好用主键盘输入,用数字键盘会有错误.

  10. Python 易错点

    1. Python查找一个变量时会按照“局部作用域”, “嵌套作用域”, “全局作用域”,“内置作用域”的顺序进行搜索. 在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于 ...