Description

为了 随时 与 rainbow快速交流, Freda制造了 两部传呼机 。Freda和 rainbow所在的地方有N座房屋、M条双向 光缆 。每条光缆连接两座房屋, 传呼机发出的信号只能沿着光缆传递,并且 传呼机的信号 从光缆的其中一端传递到另需要花费 t单位时间 。现在 Freda要 进行 Q次试验, 每次选取两座房屋,并想知道 传呼机的信号在这两座房屋之间传递 至少需 要多长时间。 Freda 和 rainbow简直弱爆了有木有 ,请你帮他们吧……
N座房屋 通过光缆 一定是连通的, 并且这 M条光缆有以下三类连接情况:

A:光缆不形成环 ,也就是光缆仅 有 N-1条。
B:光缆只 形成一个环,也就是光缆 仅有 N条。
C:每条光缆仅在一个环中。

Input
第一行 包含三个用空格隔开的整数, N、M和 Q。
接下来 M行每三个整数 x、y、t,表示 房屋 x和 y之间有一条传递时为 t的光缆 。
最后 Q行每两个整数 x、y,表示 Freda想知道 在 x和 y之间传呼最少需要多长时间。

Output
输出 Q行,每一个整数表示 Freda每次试验的结果 。

解题报告

A类直接LCA
B类考虑两种情况: 去掉一条边成树的情况,然后再加上那条边,求到那条边两个端点的距离再加上那条边的长度,取MINMIN。
C类:传说中的业界毒瘤仙人掌图。
可以先去环。
考虑一个这样的图:

要求5到3之间最短路径。
可以为每个环规定一个环顶,然后将环内其他顶点向环顶连边。这条边的权值就是该点到环顶的最小距离。
这个可以一边dfs求出环的总长度,然后将环长度减去一条路径的长度就是另一条路径的长度了。

因为在同一个环之前的最小路径唯一,所以直接lca就可以了。
先把5上升到与3的lca下的第一层,然后看他们是否在同一环内。如果是的话,就求环内最小距离+lca,如果不是的话就直接原lca长度+两条连往lca的边即可即可。

环内最小距离如何求?
记录一下两点走两条路径到环顶的距离的距离。然后就可以愉快的分类讨论:经过环顶,不经过环顶了。

CODE

varhh,hu,pr,su,tw,w,tnext,next,e,te:array[-60000..60000] of longint;len,dst,s,deep,father,thead,head:array[0..10000] of longint;vis:array[1..10000] of boolean;f,g:array[0..10000,0..14] of longint;rt,i,ru,l,r,k,ttot,tot,n,m,q,j,x,y,t,ht:longint;
procedure new(a,b,t:longint);
begininc(tot);e[tot]:=b;  w[tot]:=t;next[tot]:=head[a];head[a]:=tot;e[tot+m]:=a;  w[tot+m]:=t;next[tot+m]:=head[b];head[b]:=tot+m;
end;
procedure tnew(a,b,t:longint);
begininc(ttot);te[ttot]:=b;  tw[ttot]:=t;tnext[ttot]:=thead[a];thead[a]:=ttot;te[ttot+m]:=a;  tw[ttot+m]:=t;tnext[ttot+m]:=thead[b];thead[b]:=ttot+m;
end;
function min(a,b:longint):longint;
beginif a>b then exit(b) else exit(a);
end;
procedure swap(var a,b:longint);
var t:longint;
begint:=a; a:=b; b:=t;
end;function lca(x,y:longint):longint;
var i:longint;
beginlca:=0;if deep[x]<deep[y] then swap(x,y);for i:=14 downto 0 doif deep[g[x,i]]>deep[y] thenbegininc(lca,f[x,i]);x:=g[x,i];end;if deep[x]<>deep[y] thenbegininc(lca,f[x,0]);x:=g[x,0];end;if x=y then exit(lca);for i:=14 downto 0 doif g[x,i]<>g[y,i] thenbegininc(lca,f[x,i]+f[y,i]);x:=g[x,i]; y:=g[y,i];end;if (hh[x]=hh[y])and(hh[x]+hh[y]<>0)and(m>n-1) thenbeginexit(lca+min(abs(pr[x]-pr[y]),min(pr[x]+su[y],pr[y]+su[x])));end else exit(lca+f[x,0]+f[y,0]);
end;procedure init_lca(x:longint);
beginfor i:=1 to 14 dobeging[x,i]:=g[g[x,i-1],i-1];f[x,i]:=f[g[x,i-1],i-1]+f[x,i-1];end;
end;procedure circle(x,fa,way,lastpath:longint);
var i,k:longint;
begininc(s[0]); s[s[0]]:=x;dst[x]:=way;vis[x]:=true;k:=head[x];while (k<>0) dobeginif vis[e[k]]=false thencircle(e[k],x,way+w[k],k)elseif (hu[k]=0)and(k<>lastpath+m)and(k<>lastpath-m) thenbeginhu[k]:=1; hu[k-m]:=1; hu[k+m]:=1;i:=s[0];len[e[k]]:=dst[x]-dst[e[k]]+w[k];inc(ht);while s[i]<>e[k] dobeginhh[s[i]]:=ht;father[s[i]]:=e[k];pr[s[i]]:=dst[s[i]]-dst[e[k]];su[s[i]]:=len[e[k]]-(dst[s[i]]-dst[e[k]]);tnew(e[k],s[i],min(dst[s[i]]-dst[e[k]],len[e[k]]-(dst[s[i]]-dst[e[k]])));dec(i);end;end;k:=next[k];end;if (hh[x]=0)and(fa<>0) thenbegintnew(fa,x,w[lastpath]);end;dec(s[0]);
end;
procedure dfs(x,way,dep,fa:longint);
vark:longint;
begindst[x]:=way;deep[x]:=dep;init_lca(x);k:=thead[x];while k<>0 dobeginif te[k]<>fa thenbeginf[te[k],0]:=tw[k];g[te[k],0]:=x;dfs(te[k],way+tw[k],dep+1,x);end;k:=tnext[k];end;
end;procedure init;
begindeep[0]:=-maxlongint;readln(n,m,q);for i:=1 to m dobeginreadln(x,y,t);new(x,y,t);end;if m>n-1 then circle(1,0,0,0) elsebegintw:=w;thead:=head;tnext:=next;te:=e;ttot:=tot;end;dfs(1,0,1,0);
end;
begininit();for i:=1 to q dobeginreadln(x,y);writeln(lca(x,y));end;
end.

jzoj3395 Freda的传呼机相关推荐

  1. 【NOIP2013模拟】Freda的传呼机

    [NOIP2013模拟]Freda的传呼机 Time Limits: 100 ms Memory Limits: 131072 KB Description 为了 随时 与 rainbow快速交流, ...

  2. JZOJ3395. 【NOIP2013模拟】Freda的传呼机

    题目大意 给一个包含N个节点和M条双向边的图(保证每条边只会最多出现在一个环中,即仙人掌)和Q个询问. 输入x,y,t表示x,y之间有一条长度为t的双向边. 接下来Q个询问,每个询问(u,v)求(u, ...

  3. Acwing 360. Freda的传呼机(仙人掌图重构,lca)

    为了随时与rainbow快速交流,Freda制造了两部传呼机.Freda和rainbow所在的地方有N座房屋.M 条双向光缆. 每条光缆连接两座房屋,传呼机发出的信号只能沿着光缆传递,并且传呼机的信号 ...

  4. 「Nescafé26」 Freda的传呼机 【树上倍增+图论】

    题目: 为了随时与rainbow快速交流,Freda制造了两部传呼机.Freda和rainbow所在的地方有N座房屋.M条双向光缆.每条光缆连接两座房屋,传呼机发出的信号只能沿着光缆传递,并且传呼机的 ...

  5. 「Nescafé26」 Freda的传呼机 【最短路径+树上倍增】

    题目: 为了随时与rainbow快速交流,Freda制造了两部传呼机.Freda和rainbow所在的地方有N座房屋.M条双向光缆.每条光缆连接两座房屋,传呼机发出的信号只能沿着光缆传递,并且传呼机的 ...

  6. 【BZOJ30472125】Freda的传呼机

    Description 为了 随时 与 rainbow快速交流, Freda制造了 两部传呼机 .Freda和 rainbow所在的地方有N座房屋.M条双向 光缆 .每条光缆连接两座房屋, 传呼机发出 ...

  7. 【NOIP2013模拟】Freda的传呼机 题解+代码

    这题又有点像码农题!! Description 为了 随时 与 rainbow快速交流, Freda制造了 两部传呼机 .Freda和 rainbow所在的地方有N座房屋.M条双向 光缆 .每条光缆连 ...

  8. bzoj3047: Freda的传呼机 2125: 最短路

    Description 为了随时与rainbow快速交流,Freda制造了两部传呼机.Freda和rainbow所在的地方有N座房屋.M条双向光缆.每条光缆连接两座房屋,传呼机发出的信号只能沿着光缆传 ...

  9. bzoj3047: Freda的传呼机bzoj2125: 最短路

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3047 http://www.lydsy.com/JudgeOnline/problem.ph ...

最新文章

  1. java 实现 DES加密 解密算法
  2. Ubuntu用apt-get安装报错:E: Could not get lock /var/lib/dpkg/lock-frontend - open (11:资源暂时不可用)
  3. PyQt5 技术篇-在clipboard.dataChanged.connect()里如何写入剪切板示例演示,pyqt5监听剪切板变动并写入剪切板内容
  4. Android Studio中有没有类似于Eclipse中的ctrl+2+L的快捷键? \Android Studio快捷键之代码提示...
  5. Java黑皮书课后题第6章:*6.2(求一个整数各位数字之和)编写一个方法,计算一个整数各位数字之和。使用下面的方法头:public static int sumDigits(long n)
  6. opencv 像素操作
  7. Codeforces 474 C. Captain Marmot
  8. DE29 Matrix Exponentials
  9. Codeforces Round #173 (Div. 2) E. Sausage Maximization —— 字典树 + 前缀和
  10. STM32实现四驱小车(二)通信任务——遥控器SBUS通信
  11. 声纹识别demo_BirdSongDemo 一款基于鸟叫声识别的通用鸟类识别软件LilyBirdSong 联合开发网 - pudn.com...
  12. linux7 镜像文件,{红帽 RHCE}RHEL7使用ISO镜像文件构筑本地YUM
  13. 怎么批量修改pdf文件名?
  14. opencv实现图片及视频流(摄像头)的人脸检测
  15. 【axios】get和post请求用法
  16. SVG_16_defs标签_use标签_style标签_红绿灯效果
  17. 01GOF23-创建模型式
  18. unity - 二进制文件操作-存储与读取
  19. (一)Apollo配置中心介绍
  20. 《Total Commander:万能文件管理器》——12.6. 附录

热门文章

  1. HOG+SVM实现行人检测
  2. 在linux搭建wiki教程,在Ubuntu 16.04系统上安装WikkaWiki
  3. 交叉编译Qt5.9.6
  4. bw项目抱佛脚入门资料-2.按照指标创建BW数据存储对象
  5. Ae 入门系列之五:效果和预设
  6. oracle修改分区表的默认空间,Oracle数据库学习_Oracle分区表的分区占用空间为什么是8M?如何修改分区的初始空间?...
  7. 简述python语言的主要功能和特点_计算机考试简答题
  8. 没有想到,网易首席架构师竟用了500页笔记,把网络协议给趣谈了
  9. (图解)设置封面中的下划线一样长
  10. R语言-回归系数的极大似然估计