题目描述

八中里面有N个建设物,M条边。对于这种要建最小生成树的问题,你应该很熟练了。现在老大决定降低某条边的费用,然后这条边必须要被选中,因为这条路他每天都要走,自然......问选了这条边后是否可以得到一个比从前总开支相等或更小的方案。

输入格式

第一行三个整数N,M,Q(1<=N<=1000,N-1<=M<=100000接下来M行,每行三个整数(X,Y,Z)描述一条可以建造的路。 0<=Z<=10000 最后Q行,每行两个整数i,x(1<=i<=M,0<=x)描述一个修改计划,即要你判断如果 将第i条公路的修建费用降低为x元后,是否可以得到一个比从前总开支相等或更小的方案

输出格式

按顺序输出Q行,每行输出"Yes"或"No",Yes表示可以建造,No表示不可能


先考虑暴力。

我们可以每次询问之后都修改一次边权,然后在原图求一次最小生成树,看是否更优即可。时间复杂度为O(Q * MlogM)

其实在原图再求一次mst时基本上所有边都是不需要变动的。可以利用这一点考虑优化

如果询问给出的边是树上边,那么只需比较和原来的树边大小即可。

如果不是树上边,那么如果原树不变,只加上询问的边,就会形成一个环。设询问给出的边为E(u,v),那么这个环就可以表示为:u->LCA(u,v)->v->u。所以生成树上唯一需要改变的就是这个环上的部分。只需要把环断掉一条边即可。为了使断掉之后的生成树尽可能小,我们肯定会断掉环上最长的边(除了询问给的边)。所以问题就变成了:求路径u->LCA(u,v)->v上最长边。

可以用倍增做,时间复杂度为O((N+M)logN),总复杂度就是:O((N+Q)logN+MlogM)。也可以树剖直接做,复杂度为O(QlogNlogN+MlogM)。

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #define maxn 1001
  6. #define maxm 100001
  7. using namespace std;
  8. struct brim{
  9. int u,v,w;
  10. bool operator<(const brim &b)const{ return w<b.w; }
  11. }b[maxm],tmp[maxm];
  12. struct edge{
  13. int to,dis,next;
  14. edge(){}
  15. edge(const int &_to,const int &_dis,const int &_next){ to=_to,dis=_dis,next=_next; }
  16. }e[maxn<<1];
  17. int head[maxn],k;
  18. struct node{
  19. int l,r,c;
  20. }t[maxn<<2];
  21. int anc[maxn];
  22. int size[maxn],fa[maxn],son[maxn],dep[maxn];
  23. int top[maxn],dfn[maxn],id[maxn],tot;
  24. bool vis[maxn];
  25. int n,m,q,val[maxn];
  26. inline int read(){
  27. register int x(0),f(1); register char c(getchar());
  28. while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
  29. while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
  30. return x*f;
  31. }
  32. inline void add(const int &u,const int &v,const int &w){
  33. e[k]=edge(v,w,head[u]);
  34. head[u]=k++;
  35. }
  36. int get(int x){ return anc[x]==x?x:anc[x]=get(anc[x]); }
  37. inline int kruskal(){
  38. for(register int i=1;i<=n;i++) anc[i]=i;
  39. for(register int i=1;i<=m;i++) tmp[i]=b[i];
  40. sort(tmp+1,tmp+1+m);
  41. for(register int i=1;i<=m;i++){
  42. int u=tmp[i].u,v=tmp[i].v,w=tmp[i].w;
  43. if(get(u)==get(v)) continue;
  44. anc[get(u)]=get(v),add(u,v,w),add(v,u,w);
  45. }
  46. }
  47. void dfs_getson(int u){
  48. size[u]=1;
  49. for(register int i=head[u];~i;i=e[i].next){
  50. int v=e[i].to;
  51. if(v==fa[u]) continue;
  52. dep[v]=dep[u]+1,fa[v]=u;
  53. dfs_getson(v);
  54. size[u]+=size[v];
  55. if(size[v]>size[son[u]]) son[u]=v;
  56. }
  57. }
  58. void dfs_rewrite(int u,int tp){
  59. top[u]=tp,dfn[u]=++tot,id[tot]=u;
  60. if(son[u]) dfs_rewrite(son[u],tp);
  61. for(register int i=head[u];~i;i=e[i].next){
  62. int v=e[i].to;
  63. if(v!=son[u]&&v!=fa[u]) dfs_rewrite(v,v);
  64. }
  65. }
  66. inline void endow(){
  67. for(register int i=0;i<k;i+=2){
  68. int u=e[i].to,v=e[i^1].to;
  69. if(dep[u]>dep[v]) swap(u,v);
  70. val[v]=e[i].dis;
  71. }
  72. }
  73. void build(int d,int l,int r){
  74. t[d].l=l,t[d].r=r;
  75. if(l==r){ t[d].c=val[id[l]]; return; }
  76. int mid=l+r>>1;
  77. build(d<<1,l,mid),build(d<<1|1,mid+1,r);
  78. t[d].c=max(t[d<<1].c,t[d<<1|1].c);
  79. }
  80. int getmax(int d,const int &l,const int &r){
  81. if(l<=t[d].l&&t[d].r<=r) return t[d].c;
  82. int mid=t[d].l+t[d].r>>1,ans=0;
  83. if(l<=mid) ans=max(ans,getmax(d<<1,l,r));
  84. if(r>mid) ans=max(ans,getmax(d<<1|1,l,r));
  85. return ans;
  86. }
  87. int main(){
  88. memset(head,-1,sizeof head);
  89. n=read(),m=read(),q=read();
  90. for(register int i=1;i<=m;i++) b[i].u=read(),b[i].v=read(),b[i].w=read();
  91. kruskal();
  92. dfs_getson(1);
  93. dfs_rewrite(1,1);
  94. endow();
  95. build(1,1,tot);
  96. for(register int i=1;i<=q;i++){
  97. int id=read(),w=read(),mmax=0,u=b[id].u,v=b[id].v;
  98. while(top[u]!=top[v]){
  99. if(dep[top[u]]>dep[top[v]]) swap(u,v);
  100. mmax=max(mmax,getmax(1,dfn[top[v]],dfn[v]));
  101. v=fa[top[v]];
  102. }
  103. if(dep[u]>dep[v]) swap(u,v);
  104. if(u!=v) mmax=max(mmax,getmax(1,dfn[u]+1,dfn[v]));
  105. printf("%s\n",mmax-w>=0?"Yes":"No");
  106. }
  107. return 0;
  108. }

入门OJ:八中生成树2的更多相关文章

  1. 【入门OJ】2003: [Noip模拟题]寻找羔羊

    这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...

  2. 【大视野入门OJ】1099:歌德巴赫猜想

    Description 歌德巴赫猜想大家都很熟悉吧?给一个数,能够分解成两个素数的和.现在要给你一个n,6 <= n < 1000000,让你求他会分解成哪两个素数?如果存在多组解,则要求 ...

  3. 【大视野入门OJ】1083:数组的二分查找

    Description 在1500个整数中查整数x的位置,这些数已经从小到大排序了.若存在则输出其位置,若不存在则输出-1. Input 第一行,一个整数x 后面1500行,每行一个整数 Output ...

  4. 入门oj 6492: 小B的询问

    Description 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L ...

  5. 入门oj 5499: 讲话模式

    Description 每个人说话都有口头禅,现给出一个字符串,请求出其中出现次数最多的单词(不区分大小写). Input 输入一行,长度小于等于1048576的字符串输入至少包含一个字母或数字 Ou ...

  6. 入门oj 6451: The XOR Largest Pair之二

    Description 今天小W用了1s不到的时候完成了这样一个题:在给定的N个整数 A_1,A_2,-,A_N中选出两个进行异或运算,得到的结果最大是多少?正当他志得意满时,L老师亮出了另一个题:给 ...

  7. 入门OJ:photo

    题目描述 有N个人,来自K个家族.他们排成一行准备照相,但是由于天生的排外性,每个人都希望和本家族的人站在一起,中间不要加入别的家族的人.问最少从队列中去掉多少个就可以达到这个目的. 输入格式 第一行 ...

  8. 入门OJ:简单的网络游戏

    题目描述 在某款极具技术含量的网络游戏中,佳佳靠着他的聪明智慧垄断了游戏中的油田系统.油田里有许多油井,这些油井排成一个M*N的矩形.每个油井都有一个固定的采油量.每两个相邻的油井之间有一条公路,这些 ...

  9. 入门OJ:Coin

    题目描述 你有n个硬币,第i硬币面值为ai,现在总队长想知道如果丢掉了某个硬币,剩下的硬币能组成多少种价值?(0价值不算) 输入格式 第一行一个整数n 第二行n个整数.,a1,a2-an. 1< ...

随机推荐

  1. 图解Janusgraph系列-并发安全:锁机制(本地锁+分布式锁)分析

    图解Janusgraph系列-并发安全:锁机制(本地锁+分布式锁)分析 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步(超链):图数据 ...

  2. Java篇:Docker的介绍安装 和常用命令

    文章目录 为什么 出现docker Docker的简介 容器(Container) 镜像(Image) 仓库(Repository) Docker的安装 查看容器 删除镜像 删除容器 部署应用 以my ...

  3. 小白数据分析——Python职位全链路分析

    最近在做Python职位分析的项目,做这件事的背景是因为接触Python这么久,还没有对Python职位有一个全貌的了解.所以想通过本次分析了解Python相关的职位有哪些.在不同城市的需求量有何差异 ...

  4. 响应式网站设计---Bootstrap

    响应式布局可以帮助我们实现网站布局随屏幕大小自动调整的需求,实现不同屏幕分辨率的终端上浏览网页的不同展示方式,使得网页在PC端和手机端均可以完美的展现其内容,具有自适应性. 使用基于Bootstrap ...

  5. 豆瓣读书top250数据爬取与可视化

    爬虫–scrapy 题目:根据豆瓣读书top250,根据出版社对书籍数量分类,绘制饼图 搭建环境 import scrapy import numpy as np import pandas as p ...

  6. python爬虫爬取安居客并进行简单数据分析

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 爬取过程一.指定爬取数据二.设置请求头防止反爬三.分析页面并且与网页源码进行比对四.分析页面整理数据 ...

  7. python初学者-使用for循环用四位数组成不同的数

    digits = (1,2,3,4) for i in digits: for j in digits: if j==i: continuefor k in digits: if k==i or k= ...

  8. jsp文件导包

    可以在一个页面中用上多个<% @ page %>指令,但是其中的属性只能用一次,不过也有个例外,那就是import属性.因为import属性和Java中的import语句差不多(参照Jav ...

  9. 2.2.1 Sqoop1的基本架构

    当用户通过shell命令提交迁移作业后,Sqoop会从关系型数据库中读取元信息,并根据并发度和数据表大小将数据划分成若干分片,每片交给一个Map Task处理,这样多个Map Task同时读取数据库中 ...

  10. linux系统修改Swap分区【转】

    在装完Linux系统之后自己去修改Swap分区的大小(两种方法) 在安装完Linux系统后,swap分区太小怎么办,怎么可以扩大Swap分区呢?有两个办法,一个是从新建立swap分区,一个是增加swa ...