1576: [Usaco2009 Jan]安全路经Travel

Time Limit: 10 Sec  Memory Limit: 64 MB

Submit: 665  Solved: 227
[Submit][Status]

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

输出解释:

跟题中例子相同

HINT

 

Source

  这道题本来的思路是对于每个子树维护一个单调队列,但是看着写链剖都能T的那么惨,还是老老实实写链剖吧。
  这道题给我最大的启示是:最短路用spfa是非常作死的。。。。。不过以前我都默认spfa最坏为nlogn的。
  至少我一整个下午都没有想到usaco的题居然还要卡spfa。
 
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. #define MAXN 110000
  7. #define MAXQ MAXN*20
  8. #define MAXE (MAXN*4 +MAXN*2)
  9. #define MAXV MAXN
  10. #define INF 0x3f3f3f3f
  11. #define lch (now<<1)
  12. #define rch (now<<1^1)
  13. int n,m;
  14. inline int nextInt()
  15. {
  16. register int x=;
  17. register char ch;
  18. while (ch=getchar(),ch<'' || ch>'');
  19. while (x=x*+ch-'',ch=getchar(),ch<='' && ch>='');
  20. return x;
  21. }
  22. struct sgt_node
  23. {
  24. int l,r,val,lazy;
  25. }sgt[MAXN*];
  26. inline void down(int now)
  27. {
  28. sgt[lch].val=min(sgt[lch].val,sgt[now].val);
  29. sgt[rch].val=min(sgt[rch].val,sgt[now].val);
  30. }
  31. void Build_sgt(int now,int l,int r)
  32. {
  33. sgt[now].l=l;sgt[now].r=r;
  34. if (sgt[now].l==sgt[now].r)
  35. {
  36. sgt[now].val=INF;
  37. return ;
  38. }
  39. Build_sgt(lch,l,(l+r)>>);
  40. Build_sgt(rch,((l+r)>>)+,r);
  41. sgt[now].val=max(sgt[lch].val,sgt[rch].val);
  42. }
  43. void Modify_sgt(int now,int l,int r,int v)
  44. {
  45. if (sgt[now].l==l && sgt[now].r==r)
  46. {
  47. sgt[now].val=min(sgt[now].val,v);
  48. return ;
  49. }
  50. down(now);
  51. int mid=(sgt[now].l+sgt[now].r)>>;
  52. if (r<=mid)
  53. Modify_sgt(lch,l,r,v);
  54. else if (mid<l)
  55. Modify_sgt(rch,l,r,v);
  56. else
  57. Modify_sgt(lch,l,mid,v),Modify_sgt(rch,mid+,r,v);
  58. }
  59. int Query_sgt(int now,int pos)
  60. {
  61. if (sgt[now].l==sgt[now].r)return sgt[now].val;
  62. if (pos<=((sgt[now].l+sgt[now].r)>>))
  63. return min(sgt[now].val,Query_sgt(lch,pos));
  64. else
  65. return min(sgt[now].val,Query_sgt(rch,pos));
  66. }
  67. struct Edge
  68. {
  69. int np,val;
  70. Edge *next;
  71. Edge *neg;
  72. }E[MAXE],*V[MAXV],*V2[MAXV];
  73. int tope=-;
  74. inline void addedge(int x,int y,int z)
  75. {
  76. E[++tope].np=y;
  77. E[tope].val=z;
  78. E[tope].next=V[x];
  79. V[x]=&E[tope];
  80. }
  81. inline void addedge2(int x,int y,int z)
  82. {
  83. E[++tope].np=y;
  84. E[tope].val=z;
  85. E[tope].next=V2[x];
  86. V2[x]=&E[tope];
  87. }
  88. int q[MAXQ];
  89. bool vis[MAXN];
  90. int pnt[MAXN];
  91. int dis[MAXN];
  92. Edge *pne[MAXN];
  93. /*
  94. void spfa(register int now)
  95. {
  96. register int head=-1,tail=0;
  97. memset(dis,INF,sizeof(dis));
  98. q[0]=now;
  99. dis[now]=0;
  100. register Edge *ne;
  101. while (head!=tail)
  102. {
  103. head++;
  104. if (head==MAXQ)head=0;
  105. now=q[head];
  106. vis[now]=false;
  107. for (ne=V[now];ne;ne=ne->next)
  108. {
  109. if (dis[ne->np]>dis[now]+ne->val)
  110. {
  111. dis[ne->np]=dis[now]+ne->val;
  112. pne[ne->np]=ne->neg;
  113. pnt[ne->np]=now;
  114. if (!vis[ne->np])
  115. {
  116. tail++;
  117. if (tail==MAXQ)tail=0;
  118. q[tail]=ne->np;
  119. vis[ne->np]=true;
  120. }
  121. }
  122. }
  123. }
  124. }*/
  125. pair<int,int> h[MAXQ];
  126. void dijkstrea(int now)
  127. {
  128. memset(dis,INF,sizeof(dis));
  129. dis[now]=;
  130. int toph=;
  131. Edge *ne;
  132. h[toph]=make_pair(-,now);
  133. push_heap(h,h+(++toph));
  134. while (~toph)
  135. {
  136. if (h[].first!=-dis[h[].second])
  137. {
  138. pop_heap(h,h+(toph--));
  139. continue;
  140. }
  141. for (ne=V[h[].second];ne;ne=ne->next)
  142. {
  143. if (dis[ne->np]>dis[h[].second] + ne->val)
  144. {
  145. dis[ne->np]=dis[h[].second]+ne->val;
  146. pnt[ne->np]=h[].second;
  147. pne[ne->np]=ne->neg;
  148. h[toph]=make_pair(-dis[ne->np],ne->np);
  149. push_heap(h,h+(++toph));
  150. }
  151. }
  152. pop_heap(h,h+(toph--));
  153. }
  154. }
  155. int son[MAXN];
  156. int top[MAXN];
  157. int depth[MAXN];
  158. int pos[MAXN],dfstime=;
  159. int dfs1(int now)
  160. {
  161. register Edge *ne;
  162. int mxsiz=;
  163. int siz=,t;
  164. for (ne=V2[now];ne;ne=ne->next)
  165. {
  166. depth[ne->np]=depth[now]+;
  167. siz+=t=dfs1(ne->np);
  168. if (t>mxsiz)
  169. {
  170. mxsiz=t;
  171. son[now]=ne->np;
  172. }
  173. }
  174. return siz;
  175. }
  176. void dfs2(int now,int tp)
  177. {
  178. register Edge *ne;
  179. pos[now]=++dfstime;
  180. top[now]=tp;
  181. if (~son[now])
  182. dfs2(son[now],tp);
  183. for (ne=V2[now];ne;ne=ne->next)
  184. {
  185. if (ne->np==son[now])continue;
  186. dfs2(ne->np,ne->np);
  187. }
  188. }
  189. int lca(register int x,register int y)
  190. {
  191. while (x!=y)
  192. {
  193. if (top[x]==top[y])
  194. {
  195. if (depth[x]<depth[y])return x;
  196. else return y;
  197. }
  198. if (depth[top[x]]<depth[top[y]])swap(x,y);
  199. x=pnt[top[x]];
  200. }
  201. return x;
  202. }
  203. void work()
  204. {
  205. register Edge *ne;
  206. register int now,i,d,t;
  207. for (i=;i<=n;i++)
  208. {
  209. for(ne=V[i];ne;ne=ne->next)
  210. {
  211. now=i;
  212. if (ne==pne[now])continue;
  213. d=dis[ne->np]+ne->val +dis[now];
  214. t=lca(ne->np,now);
  215. if (t==now)continue;
  216. while (true)
  217. {
  218. if (depth[top[now]]==depth[top[t]])
  219. {
  220. if (pos[t]+<=pos[now])
  221. Modify_sgt(,pos[t]+,pos[now],d);
  222. break;
  223. }
  224. Modify_sgt(,pos[top[now]],pos[now],d);
  225. now=pnt[top[now]];
  226. }
  227. }
  228. }
  229. int ans;
  230. for (i=;i<=n;i++)
  231. {
  232. ans=-dis[i]+Query_sgt(,pos[i]);
  233. if (ans+dis[i]==INF)
  234. printf("-1\n");
  235. else
  236. printf("%d\n",ans);
  237. }
  238. }
  239. int main()
  240. {
  241. freopen("input.txt","r",stdin);
  242. //freopen("output.txt","w",stdout);
  243. int i,j,k,x,y,z;
  244. n=nextInt();m=nextInt();
  245. for (i=;i<m;i++)
  246. {
  247. x=nextInt(),y=nextInt(),z=nextInt();
  248. addedge(x,y,z);
  249. addedge(y,x,z);
  250. V[x]->neg=V[y];
  251. V[y]->neg=V[x];
  252. }
  253. dijkstrea();
  254. memset(son,-,sizeof(son));
  255. for (i=;i<=n;i++)
  256. addedge2(pnt[i],i,INF);
  257. dfs1();
  258. dfs2(,);
  259. Build_sgt(,,dfstime);
  260. work();
  261. }

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

  1. BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)

    Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...

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

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

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

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

  4. bzoj 1576: [Usaco2009 Jan]安全路经Travel【spfa+树链剖分+线段树】

    这几天写USACO水题脑子锈住了--上来就贪心,一交就WA 事实上这个是一个叫最短路树的东西,因为能保证只有一条最短路,所以所有最短路合起来是一棵以1为根的树,并且在这棵树上,每个点被精灵占据的路是它 ...

  5. BZOJ.1576.[Usaco2009 Jan]安全路经Travel(树形DP 并查集)

    题目链接 BZOJ 洛谷 先求最短路树.考虑每一条非树边(u,v,len),设w=LCA(u,v),这条边会对w->v上的点x(x!=w)有dis[u]+dis[v]-dis[x]+len的距离 ...

  6. bzoj 1576: [Usaco2009 Jan]安全路经Travel——并查集+dijkstra

    Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...

  7. BZOJ 1576: [Usaco2009 Jan]安全路经Travel

    日常自闭半小时后看题解,太弱了qwq. 感觉这道题还是比较难的,解法十分巧妙,不容易想到. 首先题目说了起点到每个点的最短路都是唯一的,那么对这个图求最短路图必定是一棵树,而且这棵树是唯一的. 那么我 ...

  8. 【BZOJ】1576 [Usaco2009 Jan]安全路经Travel

    [算法]最短路树+(树链剖分+线段树)||最短路树+并查集 [题解] 两种方法的思想是一样的,首先题目限制了最短路树唯一. 那么建出最短路树后,就是询问对于每个点断掉父边后重新找路径的最小值,其它路径 ...

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

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

随机推荐

  1. C++ notes for beginners(2)

    作者:马 岩(Furzoom) (http://www.cnblogs.com/furzoom/)版权声明:本文的版权归作者与博客园共同所有.转载时请在明显地方注明本文的详细链接,未经作者同意请不要删 ...

  2. Repositories.EntityFramework 实现方式

    今天记录一下自己的EntityFramework数据访问层.这里用通过泛型Repository的方式实现了数据的访问.先上一张结构图. Configuration文件夹里面的类是全部实体映射类.这些类 ...

  3. Android免坑指南(一)Sugar与SQLite

    最近在Android手机开发中使用了ORM框架Sugar1.4,节省了大量代码,同时也遇到不少麻烦,记录如下: 1. 使用group by将查询结果转换为POJO对象 在Sugar1.4中,可以使用如 ...

  4. 如何注册ActiveX打印控件

    一.看系统是32位还是64位的.(以64位为例) 二.先找到你的wfPrint.OCX文件所在路径 三.找到SysWOW64所在的命令控制符 四.最后在该cmd下注册 就可以了.

  5. 利用SQL语句给字段加注释

    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'角色Id',--注释名称 @level0type=N'SCHEMA' ...

  6. json(gson) 转换html标签带来的麻烦

    gson 转换html标题时,会把html(特殊字符转换为unicode编码) ,所以为了避免这个问题GsonBuilder类 有一个 disablehtmlEscaping方法. 就可以让gson类 ...

  7. Google Android SDK开发范例------------20141119

    一.Edit和Checkbox完成对登陆密码的查看:添加Edit的setOnCheckedChageListener和对CheckBox的状态通过isCHecked判断 大体代码如下 CheckBox ...

  8. java三大特性性:封装、继承和多态

    一.封装 封装是指隐藏对象的属性及实现细节,对外仅提供接口可见.封装实现了信息隐藏,利于软件复用.其优点是达到了模块化的标准,从而提高了代码的复用程度.在某种程度上,封装也大大改善了软件开发的可维护性 ...

  9. 【技术·水】浅谈Dism++清理插件开发

    前言 昨天我发布了NCleaner,一款Dism++清理插件(地址:http://bbs.pcbeta.com/viewthread-1692182-1-1.html) 有些人想要我开源NCleane ...

  10. 坑爹CF April Fools Day Contest题解

    H - A + B Strikes Back A + B is often used as an example of the easiest problem possible to show som ...