Description

Input

* 第一行: 两个空格分开的数, N和M

* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i

Output

* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.

Sample Input

4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同

Sample Output

3
3
6
输出解释:
跟题中例子相同

解题思路:

先建出来最短路树(题目都提示到这个份上了)

然后考虑不走最后一条边那么就要从子节点走或者从一些其他非树边走。

可以证明最后只经过一条非树边

考虑非树边可以怎么走。

一条非树边可以造成的贡献就是其Lca到这两个点上的所有树边。

其答案就是ansx=disu+disv+lenu-v-disx

disx一定那么可以将disu+disv+lenu-v插入树链

最后求最小值就好了。

可以用树链剖分实现。

代码:

  1. #include<queue>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. const int N=;
  6. int tr[N<<];
  7. struct pnt{
  8. int hd;
  9. int no;
  10. int fa;
  11. int tp;
  12. int dp;
  13. int dis;
  14. int ind;
  15. int wgt;
  16. int mxs;
  17. bool vis;
  18. bool friend operator < (pnt x,pnt y)
  19. {
  20. return x.dis>y.dis;
  21. }
  22. }p[N];
  23. struct ent{
  24. int twd;
  25. int lst;
  26. int vls;
  27. bool use;
  28. }e[N<<];
  29. std::priority_queue<pnt>Q;
  30. /*class priority_queue{
  31. public:
  32. void push(pnt x)
  33. {
  34. line[++siz]=x;
  35. int nw=siz;
  36. while((nw>>1))
  37. {
  38. int nx=nw>>1;
  39. if(line[nx].dis<line[nw].dis)
  40. break;
  41. std::swap(line[nw],line[nx]);
  42. nw=nx;
  43. }
  44. return ;
  45. }
  46. void pop(void)
  47. {
  48. line[1]=line[siz--];
  49. int nw=1;
  50. while((nw<<1)<=siz)
  51. {
  52. int nx=nw<<1;
  53. if(nx<siz&&line[nx].dis>line[nx+1].dis)
  54. nx++;
  55. if(line[nw].dis<line[nx].dis)
  56. break;
  57. std::swap(line[nw],line[nx]);
  58. nw=nx;
  59. }
  60. return ;
  61. }
  62. int top(void)
  63. {
  64. return line[1].no;
  65. }
  66. bool empty(void)
  67. {
  68. return siz==0;
  69. }
  70. private:
  71. pnt line[N];
  72. int siz;
  73. }Q;*/
  74. int n,m;
  75. int cnt;
  76. int dfn;
  77. void ade(int f,int t,int v)
  78. {
  79. cnt++;
  80. e[cnt].twd=t;
  81. e[cnt].lst=p[f].hd;
  82. e[cnt].vls=v;
  83. p[f].hd=cnt;
  84. return ;
  85. }
  86. void Dij(int x)
  87. {
  88. for(int i=;i<=n;i++)
  89. {
  90. p[i].no=i;
  91. p[i].dis=0x3f3f3f3f;
  92. }
  93. p[].dis=;
  94. p[].fa=;
  95. Q.push(p[x]);
  96. while(!Q.empty())
  97. {
  98. x=Q.top().no;
  99. Q.pop();
  100. if(p[x].vis)
  101. continue;
  102. p[x].vis=true;
  103. for(int i=p[x].hd;i;i=e[i].lst)
  104. {
  105. int to=e[i].twd;
  106. if(p[to].dis>p[x].dis+e[i].vls)
  107. {
  108. p[to].fa=x;
  109. p[to].dis=p[x].dis+e[i].vls;
  110. Q.push(p[to]);
  111. }
  112. }
  113. }
  114. return ;
  115. }
  116. void Basic_dfs(int x,int f)
  117. {
  118. p[x].dp=p[f].dp+;
  119. p[x].wgt=;
  120. int maxs=-;
  121. for(int i=p[x].hd;i;i=e[i].lst)
  122. {
  123. int to=e[i].twd;
  124. if(p[to].fa!=x||to==f)
  125. {
  126. e[i].use=true;
  127. continue;
  128. }
  129. Basic_dfs(to,x);
  130. p[x].wgt+=p[to].wgt;
  131. if(maxs<p[to].wgt)
  132. {
  133. p[x].mxs=to;
  134. maxs=p[to].wgt;
  135. }
  136. }
  137. return ;
  138. }
  139. void Build_dfs(int x,int top)
  140. {
  141. if(!x)
  142. return ;
  143. p[x].tp=top;
  144. p[x].ind=++dfn;
  145. Build_dfs(p[x].mxs,top);
  146. for(int i=p[x].hd;i;i=e[i].lst)
  147. {
  148. int to=e[i].twd;
  149. if(p[to].fa!=x||p[to].ind)
  150. continue;
  151. Build_dfs(to,to);
  152. }
  153. return ;
  154. }
  155. int Lca(int x,int y)
  156. {
  157. while(p[x].tp!=p[y].tp)
  158. {
  159. if(p[p[x].tp].dp<p[p[y].tp].dp)
  160. std::swap(x,y);
  161. x=p[p[x].tp].fa;
  162. }
  163. if(p[x].dp>p[y].dp)
  164. std::swap(x,y);
  165. return x;
  166. }
  167. void update(int l,int r,int ll,int rr,int spc,int v)
  168. {
  169. if(l>rr||ll>r)
  170. return ;
  171. if(ll<=l&&r<=rr)
  172. {
  173. tr[spc]=std::min(tr[spc],v);
  174. return ;
  175. }
  176. int mid=(l+r)>>;
  177. update(l,mid,ll,rr,spc<<,v);
  178. update(mid+,r,ll,rr,spc<<|,v);
  179. return ;
  180. }
  181. int query(int l,int r,int pos,int spc)
  182. {
  183. if(l==r)
  184. return tr[spc];
  185. int ans=tr[spc];
  186. int mid=(l+r)>>;
  187. if(pos<=mid)
  188. return std::min(query(l,mid,pos,spc<<),ans);
  189. else
  190. return std::min(query(mid+,r,pos,spc<<|),ans);
  191. }
  192. int main()
  193. {
  194. memset(tr,0x6f,sizeof(tr));
  195. scanf("%d%d",&n,&m);
  196. for(int i=;i<=m;i++)
  197. {
  198. int a,b,c;
  199. scanf("%d%d%d",&a,&b,&c);
  200. ade(a,b,c);
  201. ade(b,a,c);
  202. }
  203. Dij();
  204. Basic_dfs(,);
  205. Build_dfs(,);
  206. for(int i=;i<=cnt;i+=)
  207. {
  208. int x,y;
  209. x=e[i].twd;
  210. y=e[i+].twd;
  211. int val=e[i].vls+p[x].dis+p[y].dis;
  212. int z=Lca(x,y);
  213. if(e[i].use)
  214. {
  215. while(p[x].tp!=p[z].tp)
  216. {
  217. update(,dfn,p[p[x].tp].ind,p[x].ind,,val);
  218. x=p[p[x].tp].fa;
  219. }
  220. if(x!=z)
  221. update(,dfn,p[z].ind+,p[x].ind,,val);
  222. }
  223. if(e[i+].use)
  224. {
  225. while(p[y].tp!=p[z].tp)
  226. {
  227. update(,dfn,p[p[y].tp].ind,p[y].ind,,val);
  228. y=p[p[y].tp].fa;
  229. }
  230. if(y!=z)
  231. update(,dfn,p[z].ind+,p[y].ind,,val);
  232. }
  233. }
  234. for(int i=;i<=n;i++)
  235. {
  236. int ans=0x3f3f3f3f;
  237. ans=std::min(ans,query(,dfn,p[i].ind,)-p[i].dis);
  238. if(ans==0x3f3f3f3f)
  239. ans=-;
  240. printf("%d\n",ans);
  241. }
  242. return ;
  243. }

BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)的更多相关文章

  1. bzoj 1576: [Usaco2009 Jan]安全路经Travel 树链剖分

    1576: [Usaco2009 Jan]安全路经Travel Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 665  Solved: 227[Sub ...

  2. 【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel

    有趣的思考题 Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第 ...

  3. [BZOJ1576] [Usaco2009 Jan]安全路经Travel(堆优化dijk + (并查集 || 树剖))

    传送门 蒟蒻我原本还想着跑两边spfa,发现不行,就gg了. 首先这道题卡spfa,所以需要用堆优化的dijkstra求出最短路径 因为题目中说了,保证最短路径有且只有一条,所以可以通过dfs求出最短 ...

  4. BZOJ1576 [Usaco2009 Jan]安全路经Travel

    首先用Dijkstra做出最短路生成树,设dis[p]为1到p点的最短路长度 对于一条不在生成树上的边u -> v,不妨设fa为u.v的lca 则一fa到v的路径上的任意点x都可以由u达到,走的 ...

  5. BZOJ1576: [Usaco2009 Jan]安全路经Travel(最短路 并查集)

    题意 给你一张无向图,保证从1号点到每个点的最短路唯一.对于每个点求出删掉号点到它的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1号点到它的最短路的长度 Sol emmm,考场上想了个 ...

  6. 【BZOJ1576】[Usaco2009 Jan]安全路经Travel 最短路+并查集

    [BZOJ1576][Usaco2009 Jan]安全路经Travel Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, ...

  7. [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分)

    [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分) 题面 BZOJ1576和BZOJ3694几乎一模一样,只是BZOJ3694直接给出了最短路树 ...

  8. bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)

    [题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...

  9. [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】

    题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...

随机推荐

  1. 最简单的HTML5游戏——贪吃蛇

    <html> <head> <meta charset="UTF-8"/> <title>贪吃蛇</title> < ...

  2. Android 4.3 系统裁剪——删除不使用的app及添加自己app

    删除不使用的apk 系统自带的app位置是在/android4.3/packages/apps 以下是一些APP作用分析: | |– BasicSmsReceiver | |– Bluetooth ( ...

  3. vue16 自定义键盘属性

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. javascript学习笔记总结

    1 有些浏览器可能不支持JavaScript,我们可以使用如下的方法对它们隐藏JavaScript代码. <html> <body> <script type=" ...

  5. jQuery 判断是否包含在数组中 jQuery.inArray()

    var arr = [ "mysql", "php", "css", "js" ];   $.inArray(" ...

  6. linux 配置全局jdk环境

    1.在usr/local下新建software文件夹(mkdir software),将下载的jdk和tomcat放在此文件夹下 2.解压 tar -xzvf jdk-8u191-linux-x64. ...

  7. 洛谷 P1705 爱与愁过火

    P1705 爱与愁过火 题目背景 (本道题目隐藏了两首歌名,找找看哪~~~) <爱与愁的故事第一弹·heartache>第三章. 爱与愁大神说这是ta的伤心指数,只不过现在好很多了,翻译只 ...

  8. bzoj1084【SCOI2005】最大子矩阵

    1084: [SCOI2005]最大子矩阵 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1946  Solved: 970 [Submit][id ...

  9. Android 採用HTML设计界面

    由于Android软件开发分工眼下还没有细化,程序猿往往须要负责软件界面的开发,尽管软件的界面图片已经由美工设计好了.可是假设使用layout技术把软件做成美丽的界面确实非常困难,而是也比較耗时.An ...

  10. 【Android】利用自己定义View的重绘实现拖动移动,获取组件的尺寸

    以下利用一个app来说明怎样利用自己定义View的重绘实现拖动移动.获取组件的尺寸. 例如以下图,触摸拖动,或者轻轻点击屏幕都能移动图片.假设碰到文字,则会弹出提示. 这里是利用自己定义View的重绘 ...