﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-慢点走 ，多喝水-随笔分类-ACM</title><link>http://www.cppblog.com/keroro/category/20530.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 31 May 2013 07:20:59 GMT</lastBuildDate><pubDate>Fri, 31 May 2013 07:20:59 GMT</pubDate><ttl>60</ttl><item><title>差分约束</title><link>http://www.cppblog.com/keroro/archive/2013/05/31/200711.html</link><dc:creator>笨蛋侦探</dc:creator><author>笨蛋侦探</author><pubDate>Fri, 31 May 2013 03:25:00 GMT</pubDate><guid>http://www.cppblog.com/keroro/archive/2013/05/31/200711.html</guid><wfw:comment>http://www.cppblog.com/keroro/comments/200711.html</wfw:comment><comments>http://www.cppblog.com/keroro/archive/2013/05/31/200711.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keroro/comments/commentRss/200711.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keroro/services/trackbacks/200711.html</trackback:ping><description><![CDATA[<div>差分约束(difference constraints)，对，两个关键字要理解好，&#8220;difference&#8221;简单理解就是两个节点的&#8220;差&#8221;，对应的就是图中的边权，而&#8220;约束&#8221;对应的是图的边。这个图的边权不一定都是正数，之前我一直很奇怪为什么做最短路的时候初始化dis[]为了0也可以，那是因为我没意识到边权可以为负数，而思维定势地想初始化dis[]为0，那0不就是最小路径了吗，但这里差分约束的最短路径常常是负数的，所以最短路径可以不是0！！</div><div>看网上讲解的时候要小心，很多人把最长路和最短路是不分的，乱死了。</div><div>还有很重要的一点很多人没区分开，</div><div>&nbsp; &nbsp; 求最小可行解 ==&gt; 把不等式划为dv &gt;= dx + Z的形式，即建立&lt;u,v,Z&gt;边 ==&gt; 可行解要最小，其实就是取约束条件中`最大`的约束 ==&gt; 求最长路</div><div></div><div>&nbsp; &nbsp; 解释：为什么求最小可行解要划成dv &gt;= dx + Z形式？因为这个形式暗指了&#8220;让dv尽量小&#8221;，因为此刻dv的取值区间为[du+Z, &#8734;]。</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 为什么可行解最小，即意味着取最大约束条件？这样想，如果有dv &gt;= du + Z1, dv &gt;= du + Z2，(Z1&lt;Z2)，那dv的最小取值就是du+Z2，因为du+Z1不满足第二个约束条件。</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 最后一步就好理解了，因为建图的边权就是约束值，既然上一步指要取最大约束，那当然是求最长路啦。</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 网上很多讲解没有区分开所谓的最大/最小，一会儿指可行解的最，一会儿指约束条件的最，弄得我乱了好久。</div><div></div><div>&nbsp; 顺便贴一下：</div><div>&nbsp; &nbsp; 求最大可行解 ==&gt; 把不等式划为dv &lt;= dx + Z的形式，即建立&lt;u,v,Z&gt;边 ==&gt; 其实就是取约束条件中`最小`约束 ==&gt; 求最短路</div><div></div><div></div><div>&nbsp; &nbsp; 关于源点：很多时候额外价格源点可以帮我们把一个非连通图变成连通图，而对于源点的不等式，一定要和你之前建边时的不等式形式一样，如果之前是dv &gt;= du + Z，那源点也要dv &gt;= d0 + xxx。这个xxx就是dis[]的初始值，关于如何选取xxx，下面两句话摘自百度百科：</div><div>&nbsp; &nbsp; &#8220;</div><div>&nbsp; &nbsp; &nbsp;1.如果将源点到各点的距离初始化为0，最终求出的最短路满足 它们之间相互最接近了</div><div>&nbsp; &nbsp; &nbsp;2.如果将源点到各点的距离初始化为INF(无穷大)，其中之1为0，最终求出的最短路满足 它们与该点之间相互差值最大。</div><div>&nbsp; &nbsp; &#8221;</div><div></div><div>&nbsp; &nbsp; 差分约束题目我一般是用SPFA+栈，为什么不用dijkstra+heap？因为dijkstra不能处理负环，而我们的题目可能有负环，所以干脆都用SPFA了，多数条件下，用stack的SPFA比用queue的快，why？因为常常地，用最先更新了的点去更新其它点，效果比用以前已经更新了的点(在queue的tail)好。</div><div></div><div></div><div></div><div>差分约束专题：http://972169909-qq-com.iteye.com/blog/1185527</div><div></div><div></div><div></div><div>poj 1201 &nbsp;差分约束</div><div>题意：求符合题意的最小集合Z的元素个数，约束条件:i j C，表区间[i,j]至少有C个Z集合的元素。</div><div></div><div>隐含条件是，S区间是个连续的数字区间，0 &lt;= s[i+1] - s[i] &lt;= 1，其中s[i]表0~i中有多少数字是Z集合元素。下面是隐含条件的建边。</div><div>&nbsp; &nbsp; for(int i = 0; i &lt; 50001; i++) { &nbsp; &nbsp;//@</div><div>&nbsp; &nbsp; &nbsp; &nbsp; vert[i].push_back(i+1); edge[i].push_back(0);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; vert[i+1].push_back(i); edge[i+1].push_back(-1);</div><div></div><div>&nbsp; &nbsp; }</div><div></div><div>poj 1364 &nbsp;差分约束</div><div>题意：约束条件：i, n, op, K --&gt; op分greater和less，需要满足Si + S[i+1] + S[i+2] + ... + S[i+n] &gt; K （或小于）</div><div></div><div>因为我是用dis[i]表示S0+S1+...+Si的和，所以&lt;u,v,w&gt;应该表示的意思是sum[v]-sum[u-1] = w，所以这里0也是一个点，所以源点不能取0！</div><div>//@ ?? 我在SPFA后面输出了dis[]数组来看，这些值并不符合题目的要求，那为什么整个程序是对的？如果要输出一个解的话怎么写？</div><div>&nbsp; &nbsp; 答：因为这里的dis[i]表示的是s1+s2+...+si的和，用第一个样例来说，</div><div>&nbsp; &nbsp; sample input:</div><div>&nbsp; &nbsp; &nbsp; &nbsp; 4 2</div><div>&nbsp; &nbsp; &nbsp; &nbsp; 1 2 gt 0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; 2 2 lt 2</div><div>&nbsp; &nbsp; 输出的dis[0--n] : -1 0 0 0 0</div><div></div><div>&nbsp; &nbsp; s1+s2+s3 = sum[3] - sum[1-1] = dis[3] - dis[0] = 1 , 满足gt 0</div><div>&nbsp; &nbsp; s2+s3+s4 = sum[4] - sum[2-1] = dis[4] - dis[1] = 0 , 满足lt 2</div><div>&nbsp; &nbsp; 所以，{si}的一组解应该为0,1,0,0,0.</div><div></div><div>poj 1983 &nbsp; &nbsp;差分约束</div><div>题意：给出两种约束条件，一种是P A B X，意为精确地约束A比B远X个单位；另一种V A B，意为模糊地约束A至少比B远1个单位。是否有可行解？</div><div></div><div>好点：两种约束条件，其中Precise约束可以转换为X &lt;= A-B &lt;= X</div><div>&nbsp; &nbsp; &nbsp; 有V i i 这种数据，这种数据在SPFA里会WA，在ballman_ford里AC，不过预处理一下就可以了，还是用SPFA.</div><div></div><div>hdu 3666 &nbsp;差分约束</div><div>题意：给出矩阵{Cij}，问是否存在数列{A} 和 {B}，使得对于矩阵内所有Xij满足: L &lt;= Xij * Ai / Bj &lt;= U&nbsp;</div><div></div><div>构图。用log把乘除变成加减，就可以差分约束来做了。我用的是SPFA+stack求最短路，最长路应该也是可以的。没有建源点，直接一开&gt;始把所有点push进去... &nbsp;14xx ms 过挺险的~</div><div></div> <div class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.cppblog.com/keroro/aggbug/200711.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keroro/" target="_blank">笨蛋侦探</a> 2013-05-31 11:25 <a href="http://www.cppblog.com/keroro/archive/2013/05/31/200711.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>查分约束 poj 3159 </title><link>http://www.cppblog.com/keroro/archive/2013/05/28/200649.html</link><dc:creator>笨蛋侦探</dc:creator><author>笨蛋侦探</author><pubDate>Tue, 28 May 2013 07:51:00 GMT</pubDate><guid>http://www.cppblog.com/keroro/archive/2013/05/28/200649.html</guid><wfw:comment>http://www.cppblog.com/keroro/comments/200649.html</wfw:comment><comments>http://www.cppblog.com/keroro/archive/2013/05/28/200649.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keroro/comments/commentRss/200649.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keroro/services/trackbacks/200649.html</trackback:ping><description><![CDATA[做第一道查分约束poj 3159...TLE不断。估计管理员是跟C++的STL过不去，就卡用vector的人了。。而我已经好久好久没人工写什么邻接表，前向星什么的了，就只能TLE过不了了。。换了什么dijkstra+优先队列，SPFA+stack优化，只要用vector来存边，估计都过不了。<br />下面是TLE代码，留纪念。<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;<span style="color: #0000FF; ">string</span>.h&gt;<br />#include&nbsp;&lt;stdio.h&gt;<br />#include&nbsp;&lt;vector&gt;<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><span style="color: #0000FF; ">int</span>&nbsp;n,&nbsp;m;<br /><span style="color: #0000FF; ">int</span>&nbsp;dis[30001];<br /><span style="color: #0000FF; ">bool</span>&nbsp;visit[30001];<br /><span style="color: #0000FF; ">int</span>&nbsp;S[30001],&nbsp;S_top&nbsp;=&nbsp;0;<br />vector&lt;<span style="color: #0000FF; ">int</span>&gt;&nbsp;vert[30001],&nbsp;edge[30001];<br /><span style="color: #0000FF; ">void</span>&nbsp;dijkstra(<span style="color: #0000FF; ">int</span>&nbsp;s);<br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;u,v,w;<br />&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d",&nbsp;&amp;n,&nbsp;&amp;m);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;m;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d%d",&nbsp;&amp;u,&nbsp;&amp;v,&nbsp;&amp;w);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vert[u].push_back(v);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;edge[u].push_back(w);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;dijkstra(1);&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">最长路-----不是的，是最短路！</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;printf("%d\n",&nbsp;dis[n]);<br />}<br /><span style="color: #0000FF; ">void</span>&nbsp;dijkstra(<span style="color: #0000FF; ">int</span>&nbsp;s)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(dis,&nbsp;127,&nbsp;<span style="color: #0000FF; ">sizeof</span>(dis));<br />&nbsp;&nbsp;&nbsp;&nbsp;dis[s]&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;visit[s]&nbsp;=&nbsp;<span style="color: #0000FF; ">true</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;S[++S_top]&nbsp;=&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(S_top&nbsp;&gt;&nbsp;0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;u&nbsp;=&nbsp;S[S_top--];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visit[u]&nbsp;=&nbsp;<span style="color: #0000FF; ">false</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;Size&nbsp;=&nbsp;vert[u].size(),&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Size;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;v&nbsp;=&nbsp;vert[u][i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(dis[v]&nbsp;&gt;&nbsp;dis[u]&nbsp;+&nbsp;edge[u][i])&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dis[v]&nbsp;=&nbsp;dis[u]&nbsp;+&nbsp;edge[u][i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(visit[v]&nbsp;==&nbsp;<span style="color: #0000FF; ">false</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;S[++S_top]&nbsp;=&nbsp;v;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visit[v]&nbsp;=&nbsp;<span style="color: #0000FF; ">true</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;}<br />}</div><div class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.cppblog.com/keroro/aggbug/200649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keroro/" target="_blank">笨蛋侦探</a> 2013-05-28 15:51 <a href="http://www.cppblog.com/keroro/archive/2013/05/28/200649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hdu 2433</title><link>http://www.cppblog.com/keroro/archive/2013/05/27/200622.html</link><dc:creator>笨蛋侦探</dc:creator><author>笨蛋侦探</author><pubDate>Mon, 27 May 2013 09:56:00 GMT</pubDate><guid>http://www.cppblog.com/keroro/archive/2013/05/27/200622.html</guid><wfw:comment>http://www.cppblog.com/keroro/comments/200622.html</wfw:comment><comments>http://www.cppblog.com/keroro/archive/2013/05/27/200622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keroro/comments/commentRss/200622.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keroro/services/trackbacks/200622.html</trackback:ping><description><![CDATA[<div>/*</div><div>&nbsp; &nbsp; 最短路 &nbsp;好题</div><div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp; &nbsp; 题意：给出边建图，然后分别删除各条边，问每一次删边后的所有端点的两两最短路之和，若有一对端点不连通，则返回INF</div><div></div><div>&nbsp; &nbsp; 思路：暴力解法是每次删边后都来n次最短路。这里面的冗余就是删除的边并不影响一些点的最短路树，所以这些点可以不用在删边后都来次dijkstra&gt;。标程解法就是在暴力解法上加上一些剪枝。先预处理出所有点的最短路树，记x的最短路树的和为sum[x]。现在来去掉冗余：在预处理时用used[x][u][v]记录点x的最短路树是否用到了边u--v，则删除边u--v的时候，判断点x的最短路树是否用到边u--v的，若用到，则对x做一次dijkstra，用新的sum[x]表示&gt;当前最短路树；否则用预处理的sum[x]就可以，不用再dijkstra.</div><div></div><div>&nbsp; &nbsp; dijkstra是利用`边权为1`这一特性来加快的版本，具体看:http://www.cppblog.com/keroro/archive/2013/05/27/200621.html</div><div>&nbsp; &nbsp; 这道题有很多重边，这估计也是考点之一，不好好处理重边的话会超时。</div><div><br /><br /><div></div><div>&nbsp; &nbsp; 多数题解是错的，因为hdu上的这道题的数据比较水才可以过，可以试试discuss里给的数据，下面这几个题解比较靠谱。</div><div>&nbsp; &nbsp; http://blog.csdn.net/nash142857/article/details/8253913</div><div>&nbsp; &nbsp; http://www.cnblogs.com/crisxyj/archive/2013/03/10/2952396.html</div><div>&nbsp; &nbsp; http://hi.baidu.com/novosbirsk/item/bfcf0cd201edfc2d39f6f709</div><div>&nbsp; &nbsp; 两份代码的思想是完全一样的，只是&#8220;baidu blog&#8221;那份用w[i][e]来判断i的最短路树是否包括边e，而cnblog的那份是用used[x][u][v]来判断边u--&gt;v是否xxx.</div><div></div><div></div>*/</div><div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;algorithm&gt;<br />#include&nbsp;&lt;stdio.h&gt;<br />#include&nbsp;&lt;<span style="color: #0000FF; ">string</span>.h&gt;<br />#include&nbsp;&lt;vector&gt;<br />#include&nbsp;&lt;deque&gt;<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAXN&nbsp;&nbsp;&nbsp;&nbsp;101<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;99999999<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debug&nbsp;&nbsp;&nbsp;printf("!\n")<br /><span style="color: #0000FF; ">struct</span>&nbsp;Edge&nbsp;{&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;u,v;&nbsp;}&nbsp;edge[3001];<br />vector&lt;<span style="color: #0000FF; ">int</span>&gt;&nbsp;vertex[MAXN];<br /><span style="color: #0000FF; ">int</span>&nbsp;visit[MAXN],&nbsp;sum[MAXN],&nbsp;cnt[MAXN][MAXN];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">cnt[u][v]表u--v的边有多少条，用来处理重边</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">bool</span>&nbsp;used[MAXN][MAXN][MAXN];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">used[x][u][v]x的最短路树是否用到了边u--v</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">int</span>&nbsp;n,&nbsp;m;<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;init();<br /><span style="color: #0000FF; ">void</span>&nbsp;dijkstra(<span style="color: #0000FF; ">int</span>&nbsp;s,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;when,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;flag);<br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;when&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;u,&nbsp;v;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(scanf("%d%d",&nbsp;&amp;n,&nbsp;&amp;m)&nbsp;!=&nbsp;EOF)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;m;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d",&nbsp;&amp;u,&nbsp;&amp;v);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vertex[u].push_back(v);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vertex[v].push_back(u);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;edge[i].u&nbsp;=&nbsp;u,&nbsp;edge[i].v&nbsp;=&nbsp;v;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cnt[u][v]++,&nbsp;cnt[v][u]++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;ans&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;=&nbsp;n;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dijkstra(i,&nbsp;++when,&nbsp;1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans&nbsp;+=&nbsp;sum[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;m;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;tmp&nbsp;=&nbsp;ans;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;u&nbsp;=&nbsp;edge[i].u,&nbsp;v&nbsp;=&nbsp;edge[i].v;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">forbid_u&nbsp;=&nbsp;edge[i].u,&nbsp;forbid_v&nbsp;=&nbsp;edge[i].v;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为有重边所以不能用这种方法</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;1;&nbsp;j&nbsp;&lt;=&nbsp;n;&nbsp;j++)&nbsp;<span style="color: #0000FF; ">if</span>(used[j][u][v]&nbsp;&amp;&amp;&nbsp;cnt[u][v]&nbsp;==&nbsp;1)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">不加cnt[u][v]&nbsp;==&nbsp;1会超时。。卡的就是重边，靠！</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;tmp&nbsp;=&nbsp;sum[j];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum[j]&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">vector&lt;int&gt;&nbsp;::&nbsp;iterator&nbsp;it1&nbsp;=&nbsp;find(vertex[u].begin(),&nbsp;vertex[u].end(),&nbsp;v);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">vector&lt;int&gt;&nbsp;::&nbsp;iterator&nbsp;it2&nbsp;=&nbsp;find(vertex[v].begin(),&nbsp;vertex[v].end(),&nbsp;u);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">*it1&nbsp;=&nbsp;u,&nbsp;*it2&nbsp;=&nbsp;v;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cnt[u][v]--,&nbsp;cnt[v][u]--;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dijkstra(j,&nbsp;++when,&nbsp;2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cnt[u][v]++,&nbsp;cnt[v][u]++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">*it1&nbsp;=&nbsp;v,&nbsp;*it2&nbsp;=&nbsp;u;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">本来是用erase的，超时了。&nbsp;现在换这种方法也超时了，估计find耗时太久。</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans&nbsp;=&nbsp;ans&nbsp;-&nbsp;tmp&nbsp;+&nbsp;sum[j];&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">用新的sum[j]来代替旧的tmp</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum[j]&nbsp;=&nbsp;tmp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;k&nbsp;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(k&nbsp;=&nbsp;1;&nbsp;k&nbsp;&lt;=&nbsp;n;&nbsp;k++)&nbsp;<span style="color: #0000FF; ">if</span>(visit[k]&nbsp;!=&nbsp;when)&nbsp;<span style="color: #0000FF; ">break</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">如果删边了以后j不能到达k(即k没有进过队)</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(k&nbsp;&lt;=&nbsp;n)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans&nbsp;=&nbsp;INF;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans&nbsp;==&nbsp;INF&nbsp;?&nbsp;printf("INF\n")&nbsp;:&nbsp;printf("%d\n",&nbsp;ans);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans&nbsp;=&nbsp;tmp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">不要把这个tmp和for_j里的tmp混了..</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;m;&nbsp;i++)&nbsp;cnt[edge[i].u][edge[i].v]&nbsp;=&nbsp;cnt[edge[i].v][edge[i].u]&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />因为感觉memset(cnt)会不会花更多时间</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}<br /><span style="color: #0000FF; ">void</span>&nbsp;dijkstra(<span style="color: #0000FF; ">int</span>&nbsp;s,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;when,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;flag)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;floors&nbsp;=&nbsp;1;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;cur&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;deque&lt;<span style="color: #0000FF; ">int</span>&gt;&nbsp;Q[2];<br />&nbsp;&nbsp;&nbsp;&nbsp;Q[cur].push_back(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;visit[s]&nbsp;=&nbsp;when;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(!Q[cur].empty())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;u&nbsp;=&nbsp;Q[cur].front();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q[cur].pop_front();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;Size&nbsp;=&nbsp;vertex[u].size(),&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Size;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;v&nbsp;=&nbsp;vertex[u][i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(visit[v]&nbsp;!=&nbsp;when&nbsp;&amp;&amp;&nbsp;cnt[u][v]&nbsp;&gt;&nbsp;0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(flag&nbsp;==&nbsp;1)&nbsp;used[s][u][v]&nbsp;=&nbsp;used[s][v][u]&nbsp;=&nbsp;<span style="color: #0000FF; ">true</span>;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">第一次最短路才标记used<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />因为懒得写两遍，所以要flag来标记是删边前还收删边后做的最短路，1则是预处理时的最短路，此时要标记used；2则是删边后的最短路，这个时候不能标记used.</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visit[v]&nbsp;=&nbsp;when;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum[s]&nbsp;+=&nbsp;floors;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q[1-cur].push_back(v);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;floors++;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur&nbsp;=&nbsp;1&nbsp;-&nbsp;cur;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>(!Q[cur].empty());<br />}<br /><span style="color: #0000FF; ">void</span>&nbsp;init()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(sum,&nbsp;0,&nbsp;<span style="color: #0000FF; ">sizeof</span>(sum));<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(used,&nbsp;<span style="color: #0000FF; ">false</span>,&nbsp;<span style="color: #0000FF; ">sizeof</span>(used));<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;=&nbsp;n;&nbsp;i++)&nbsp;vertex[i].clear();<br />}</div></div> <div class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.cppblog.com/keroro/aggbug/200622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keroro/" target="_blank">笨蛋侦探</a> 2013-05-27 17:56 <a href="http://www.cppblog.com/keroro/archive/2013/05/27/200622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hdu 2377 </title><link>http://www.cppblog.com/keroro/archive/2013/05/27/200621.html</link><dc:creator>笨蛋侦探</dc:creator><author>笨蛋侦探</author><pubDate>Mon, 27 May 2013 09:52:00 GMT</pubDate><guid>http://www.cppblog.com/keroro/archive/2013/05/27/200621.html</guid><wfw:comment>http://www.cppblog.com/keroro/comments/200621.html</wfw:comment><comments>http://www.cppblog.com/keroro/archive/2013/05/27/200621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keroro/comments/commentRss/200621.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keroro/services/trackbacks/200621.html</trackback:ping><description><![CDATA[<div>/*</div><div>&nbsp; &nbsp; 最短路, 终点集合到s的最远距离最短，求s. &nbsp; &nbsp;即已知终点集{d}求一s使得Min{ max{ dis(s, di) } }</div><div>&nbsp; &nbsp; 好题</div><div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp;</div><div>&nbsp;&nbsp;</div><div>&nbsp; &nbsp; 思路： &nbsp;多次单源最短路，选出最大值</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 在对每个x进行分层搜索的过程中, 用max_d[y]记录每个地区x到达地区y的最短距离中的最大值. 最后求得的Star Value就是max_d[]中的最小值.</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 由于题目的特殊性`边权都为1`，所以可以借助这一性质变换一下SPFA使其更快。</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 说个题外话，在临高时看到有个学弟拓扑排序用到&#8220;分层思想&#8221;，一直觉得很妙。就是拓扑后我们可以得到floor[i]，如果floor[i] &gt; floor[j]，即说明j是i的前驱节点（层数越小越接近root）; 而floor[i] == floor[j]的话则i，j的相对顺序无所谓，因为他们都在&#8220;同一层&#8221;。</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 这里因为边权都为1，所以SPFA可以用到上述的分层思想，层数越高，离source越远。代码里面floors就表示层数，Q是滚动队列，就是一层一层地relax后继节点。</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 注意！！千万不要以为max_d[]是最短路算法里面的dis[]，这里的max_d[i]是到点i到终点集合{di}的最大值！而常规最短路算法里的dis[]已经被省略为&#8220;层数&#8221;了，不需要记录，所以没开数组。</div><div></div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 最重要的是学到一个tip！！以前我做多次最短路的时候总要每次都初始化visit[] -&gt; false，但其实不用的，我们只要用一个变量when表示&#8220;这是第几次做SPFA(或其他)&#8220;，然后每次入队前都看&#8221;是否当前visit[v] == when就可以直到改点是否已经入过队......</div><div>*/</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;stdio.h&gt;<br />#include&nbsp;&lt;<span style="color: #0000FF; ">string</span>.h&gt;<br />#include&nbsp;&lt;vector&gt;<br />#include&nbsp;&lt;deque&gt;<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debug&nbsp;&nbsp;&nbsp;printf("!\n")<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;999999999<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAXN&nbsp;&nbsp;&nbsp;&nbsp;10000<br /><span style="color: #0000FF; ">int</span>&nbsp;n;<br /><span style="color: #0000FF; ">int</span>&nbsp;max_d[MAXN];<br /><span style="color: #0000FF; ">int</span>&nbsp;visit[MAXN];<br />vector&lt;<span style="color: #0000FF; ">int</span>&gt;&nbsp;v[MAXN];<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;SPFA(<span style="color: #0000FF; ">int</span>&nbsp;s,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;when);<br /><span style="color: #0000FF; ">void</span>&nbsp;init();<br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;cases,&nbsp;query,&nbsp;id,&nbsp;m,&nbsp;y,&nbsp;x;<br />&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d",&nbsp;&amp;cases);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(cases--)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d",&nbsp;&amp;n,&nbsp;&amp;query);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;n;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d",&nbsp;&amp;id,&nbsp;&amp;m);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(m--)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d",&nbsp;&amp;y);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v[id].push_back(y);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;when&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(query--)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d",&nbsp;&amp;m);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(m--)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d",&nbsp;&amp;x);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SPFA(x,&nbsp;++when);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;ans&nbsp;=&nbsp;INF,&nbsp;ans_id&nbsp;=&nbsp;-1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;&nbsp;MAXN;&nbsp;i++)&nbsp;<span style="color: #0000FF; ">if</span>(!v[i].empty()&nbsp;&amp;&amp;&nbsp;max_d[i]&nbsp;&lt;&nbsp;ans)&nbsp;ans&nbsp;=&nbsp;max_d[i],&nbsp;ans_id&nbsp;=&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%d&nbsp;%d\n",&nbsp;ans,&nbsp;ans_id);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}<br /><span style="color: #0000FF; ">void</span>&nbsp;init()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;MAXN;&nbsp;i++)&nbsp;v[i].clear();<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(max_d,&nbsp;0,&nbsp;<span style="color: #0000FF; ">sizeof</span>(max_d));<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(visit,&nbsp;0,&nbsp;<span style="color: #0000FF; ">sizeof</span>(visit));<br />}<br /><span style="color: #0000FF; ">void</span>&nbsp;SPFA(<span style="color: #0000FF; ">int</span>&nbsp;s,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;when)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;deque&lt;<span style="color: #0000FF; ">int</span>&gt;&nbsp;Q[2];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;cur&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;Q[cur].push_back(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;max_d[s]&nbsp;=&nbsp;max(max_d[s],&nbsp;1);<br />&nbsp;&nbsp;&nbsp;&nbsp;visit[s]&nbsp;=&nbsp;when;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;floors&nbsp;=&nbsp;1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;floors++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(!Q[cur].empty())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;at&nbsp;=&nbsp;Q[cur].front();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q[cur].pop_front();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;Size&nbsp;=&nbsp;v[at].size(),&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Size;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;to&nbsp;=&nbsp;v[at][i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(visit[to]&nbsp;!=&nbsp;when)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">是否已入队<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">max_d[to]&nbsp;=&nbsp;max(max_d[to],&nbsp;max_d[at]+1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这句是不对的，因为这个分层跟拓扑排序的分层是不一样的，拓扑排序是要在入度为0时才能加进队Q，所以可以这样写，但是这里只要第一次遇见点to就必须得入队，因为要的是最短路径</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max_d[to]&nbsp;=&nbsp;max(max_d[to],&nbsp;floors);&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">不把这句放在if外面，因为这里的max_d[to]是距离s的最短路径，最短路径也就是最小层数，最小层数在to第一次入队的时候已经得到了</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visit[to]&nbsp;=&nbsp;when;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q[1-cur].push_back(to);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur&nbsp;=&nbsp;1&nbsp;-&nbsp;cur;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>(!Q[cur].empty());<br />}</div></div> <div class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.cppblog.com/keroro/aggbug/200621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keroro/" target="_blank">笨蛋侦探</a> 2013-05-27 17:52 <a href="http://www.cppblog.com/keroro/archive/2013/05/27/200621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hdu 2586</title><link>http://www.cppblog.com/keroro/archive/2013/05/17/200341.html</link><dc:creator>笨蛋侦探</dc:creator><author>笨蛋侦探</author><pubDate>Thu, 16 May 2013 18:44:00 GMT</pubDate><guid>http://www.cppblog.com/keroro/archive/2013/05/17/200341.html</guid><wfw:comment>http://www.cppblog.com/keroro/comments/200341.html</wfw:comment><comments>http://www.cppblog.com/keroro/archive/2013/05/17/200341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/keroro/comments/commentRss/200341.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/keroro/services/trackbacks/200341.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">/*</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;最小公共祖先<br />&nbsp;&nbsp;&nbsp;&nbsp;题意:&nbsp;给出一颗无向有边权树,&nbsp;询问若干个(u,v)对的距离.<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;所谓LCA&nbsp;的Tarjan算法,&nbsp;实际上就是在建树的过程中把query中的lca给计算出来,&nbsp;所以称为`离线算法`&nbsp;.&nbsp;是的,&nbsp;本质就是这么简单,&nbsp;好多解释都搞复杂了.<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;步骤略,&nbsp;自己google.<br />&nbsp;&nbsp;&nbsp;&nbsp;理解这个算法一定要抓住`递推`的思想(也有递归在里面,&nbsp;也要抓住).<br />&nbsp;&nbsp;&nbsp;&nbsp;Tarjan是利用并查集实现的,&nbsp;在递推过程中,&nbsp;一棵树的root节点代表这棵树(联系并查集来想),&nbsp;这样做的好处是,&nbsp;如果问点i与j的lca,&nbsp;我们只要找i,j都属于的最小的哪棵子树就行了,&nbsp;因为该子树就是我们的答案.&nbsp;那如何确定是那颗子树呢?&nbsp;这一点后面再解释一下.<br />&nbsp;&nbsp;&nbsp;&nbsp;下面说Tarjan最巧妙的点了.&nbsp;因为是在建树的过程中计算所有query,&nbsp;也就表示我们此刻是否能计算某一query对(u,v)的条件是&nbsp;:&nbsp;u和v是否都已经遍历过.&nbsp;所以我们可以在遍历到点v(假设经历v的时间比u晚)的时候把query给计算出来.&nbsp;比如lcm(u,v)就是find(u).&nbsp;那此刻的find(v)和lcm(u,v)相不相等呢?&nbsp;答案是不相等,&nbsp;至少在我的代码实现上不相等.&nbsp;因为father[x]的更新是在`递归回去`的时候更新的,&nbsp;而此刻在遍历v点,&nbsp;还没递归回去呢,&nbsp;father[v]当然也就没更新啦.<br />&nbsp;&nbsp;&nbsp;&nbsp;其实上一段就已经回答了`如何确定哪棵子树是我们想要的答案`这一问题了.&nbsp;就是find(u)所代表的子树!&nbsp;注意,&nbsp;是find(u),&nbsp;不是find(v)!&nbsp;因为u是在v之前已经被遍历过了,&nbsp;并且递归回去过sub_root过了,&nbsp;也就是father[u]被更新为sub_root了,&nbsp;所以find(u)可以代表当前的sub_tree,&nbsp;即`最小包含(u,v)子树`<br /><br />下面两个解释,&nbsp;推荐一下.&nbsp;罗嗦一句,&nbsp;看代码更容易理解,&nbsp;人脑模拟一遍更容易理解<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; text-decoration: underline; ">http://www.nocow.cn/index.php/Tarjan%E7%AE%97%E6%B3%95</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; text-decoration: underline; ">http://blog.chinaunix.net/uid-1721137-id-181005.html</span><span style="color: #008000; "><br /></span><span style="color: #008000; ">*/</span><br />#include&nbsp;&lt;vector&gt;<br />#include&nbsp;&lt;stdio.h&gt;<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAXN&nbsp;&nbsp;&nbsp;&nbsp;40001<br /><span style="color: #0000FF; ">#define</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debug&nbsp;&nbsp;&nbsp;printf("!\n")<br />vector&lt;<span style="color: #0000FF; ">int</span>&gt;&nbsp;v[MAXN],&nbsp;w[MAXN],&nbsp;query[MAXN],&nbsp;ans_num[MAXN];<br /><span style="color: #0000FF; ">int</span>&nbsp;father[MAXN],&nbsp;dis[MAXN],&nbsp;ans[201];<br /><span style="color: #0000FF; ">bool</span>&nbsp;visit[MAXN];<br /><span style="color: #0000FF; ">int</span>&nbsp;n;<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;init()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;=&nbsp;n;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v[i].clear();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w[i].clear();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans_num[i].clear();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query[i].clear();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;father[i]&nbsp;=&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dis[i]&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visit[i]&nbsp;=&nbsp;<span style="color: #0000FF; ">false</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /><span style="color: #0000FF; ">int</span>&nbsp;find(<span style="color: #0000FF; ">int</span>&nbsp;x)&nbsp;<br />{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;x&nbsp;==&nbsp;father[x]&nbsp;?&nbsp;x&nbsp;:&nbsp;father[x]&nbsp;=&nbsp;find(father[x]);&nbsp;<br />}<br /><span style="color: #0000FF; ">void</span>&nbsp;Union(<span style="color: #0000FF; ">int</span>&nbsp;x,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;y)&nbsp;{&nbsp;father[find(y)]&nbsp;=&nbsp;find(x);&nbsp;}<br /><span style="color: #0000FF; ">void</span>&nbsp;Tarjan(<span style="color: #0000FF; ">int</span>&nbsp;now,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;value)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;visit[now]&nbsp;=&nbsp;<span style="color: #0000FF; ">true</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;dis[now]&nbsp;=&nbsp;value;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;Size&nbsp;=&nbsp;v[now].size(),&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Size;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;tmp&nbsp;=&nbsp;v[now][i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(visit[tmp]&nbsp;!=&nbsp;0)&nbsp;<span style="color: #0000FF; ">continue</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tarjan(tmp,&nbsp;value&nbsp;+&nbsp;w[now][i]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Union(now,&nbsp;tmp);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">注意顺序,&nbsp;先Tarjan子节点tmp,&nbsp;再更新其father[tmp],&nbsp;因为要保证在递推tmp所代表的子树时,&nbsp;father[tmp]&nbsp;=&nbsp;tmp,&nbsp;而与当前子树无关.&nbsp;递归回来的时候再把tmp代表的子树`并入`到当前树里</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;Size&nbsp;=&nbsp;query[now].size(),&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Size;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;tmp&nbsp;=&nbsp;query[now][i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!visit[tmp])&nbsp;<span style="color: #0000FF; ">continue</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">若visit[tmp]&nbsp;==&nbsp;true,&nbsp;即表示tmp节点已经遍历过,&nbsp;此时可计算相应的query</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans[ans_num[now][i]]&nbsp;=&nbsp;dis[now]&nbsp;+&nbsp;dis[tmp]&nbsp;-&nbsp;2&nbsp;*&nbsp;dis[find(tmp)];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;cases,&nbsp;Query,&nbsp;x,&nbsp;y,&nbsp;z;<br />&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d",&nbsp;&amp;cases);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(cases--)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d",&nbsp;&amp;n,&nbsp;&amp;Query);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;&nbsp;n;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d%d",&nbsp;&amp;x,&nbsp;&amp;y,&nbsp;&amp;z);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v[x].push_back(y);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w[x].push_back(z);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v[y].push_back(x);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w[y].push_back(z);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Query;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d%d",&nbsp;&amp;x,&nbsp;&amp;y);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query[x].push_back(y);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query[y].push_back(x);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans_num[x].push_back(i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ans_num[y].push_back(i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tarjan(1,&nbsp;0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Query;&nbsp;i++)&nbsp;printf("%d\n",&nbsp;ans[i]);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}</div> <div class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.cppblog.com/keroro/aggbug/200341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/keroro/" target="_blank">笨蛋侦探</a> 2013-05-17 02:44 <a href="http://www.cppblog.com/keroro/archive/2013/05/17/200341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>