【兩個雙連通分量和O(nlogn)~O(logn)線上求LCA的tarjan演算法】

來源:互聯網
上載者:User

小囧了一下,雙連通分量有兩種我是前兩天才知道的

相關概念參考byv牛的blog,這裡記幾個關鍵的點

橋就是dfn[i] < low[j]的邊(i, j)

割點就是它發出去的邊(i, j)中至少一條滿足dfn[i] <= low[j](這裡是要取等號的)

我一般求的是所謂 邊雙連通分量,實際上就是把橋去掉之後還在一起的點的集合

而這裡還有一個 點雙連通分量,這個東西實際上就是差不多把割點去掉之後還在一起的邊的集合

ps:點 <=> 邊,這個東西為什麼不反過來叫呢?

求法的話差不多,都是用tarjan演算法,不過求邊雙連通分量時還要開一個邊的棧,碰到一條滿足dfn[i] <= low[j]的邊就退一次棧一直退到這條邊

還有一個東西就是那個求LCA的演算法

它用到的主要思想就是倍增,求出每個點往上跳2^j步後的點,從而使一個點可以以O(logn)的複雜度跳到它的某個祖先跟前

但是怎麼每次詢問具體怎麼做呢?

第一個簡陋的想法就是二分lca的深度,再跳,再判——但是這樣一來,每次詢問的複雜度就達到了O((logn)^2),不太理想

有直接logn的方法嗎?顯然是有的,先讓詢問的點對(i, j)中深度大的先跳到兩個深度一樣的地方,再兩個一起跳,這樣就是O(logn)的複雜度了,不過常數乘了個2

有只跳一輪的方法嗎?暫時還沒想到

另外,我為什麼在這裡提一下這個並不是特別漂亮的LCA的方法呢?

儘管這個方法無論是時間還是空間都不是最優的,但它有一個巨大的優勢,線上和可擴充

ghy大牛論文中利用歐拉序列求lca的方法難以擴充,無法在求lca的同時求一些附加資訊諸如路徑上的權值和之類的

有一個離線O(n+q)利用了並查集的方法雖然可擴充性比較強,可是卻是離線的

還有一點,這個方法所需求的資訊很少,僅用父親標記法的樹就能求出所有東西,而其他的方法都需要把樹用鄰接表存下來才行

這個優勢其實是相當有用的——在一些“擴充版”的樹中要求lca的時候這個方法就有著編程複雜度小的優勢了

比方說在cactus圖(仙人掌圖,圖中的每條點最多屬於一個簡單環)中,或是yt的最短路那道題中的每條邊最多屬於一個簡單環的圖,如果把一個點能擴充出的塊中的點的父親都改成它,最後這個圖就成了一棵樹

我們實際上比較容易求出的是最後那棵樹的父親標記法,如果再要重建一個鄰接表無疑就麻煩了,這個時候用這個方法求lca就很方便了

 

附集訓隊yt-最短路的代碼,包含了上面說的大部分演算法

program syj;<br />uses<br /> math;<br />var<br /> e,i,j,k,l,ed,tb,t,tp,n,m,task,jj,md:longint;<br /> h,a,b,sk,q,low,d,p,f,s:array[0..10005]of longint;<br /> next,point,w:array[0..40005]of longint;<br /> v:array[0..10005]of boolean;<br /> u:array[0..40005]of boolean;<br /> fa,g:array[0..15,0..10005]of longint;<br />procedure work;<br />begin<br /> i:=point[b[1]];k:=0;<br /> inc(tb);<br /> for j:=2 to b[0] do begin<br /> k:=k+w[b[j-1]];<br /> jj:=point[b[j]];<br /> f[jj]:=tb;fa[0,jj]:=i;<br /> p[jj]:=k;<br /> end;<br /> s[tb]:=k+w[b[b[0]]];<br /> for j:=2 to b[0] do begin<br /> jj:=point[b[j]];<br /> g[0,jj]:=min(p[jj],s[tb]-p[jj]);<br /> end;<br />end;<br />procedure dfs(i:longint);<br />var j,k:longint;<br />begin<br /> inc(t); a[i]:=t;low[i]:=t;<br /> inc(tp); sk[tp]:=i;<br /> v[i]:=true; j:=h[i];<br /> while j<>0 do begin<br /> k:=point[j];<br /> if not u[j] then begin<br /> u[j]:=true;u[j xor 1]:=true;<br /> inc(ed);q[ed]:=j;<br /> if a[k]=0 then begin<br /> dfs(k);<br /> if low[k]<low[i] then low[i]:=low[k];<br /> end else<br /> if v[k]and(a[k]<low[i]) then low[i]:=a[k];<br /> if low[k]>=a[i] then begin<br /> b[0]:=0;<br /> while q[ed+1]<>j do begin<br /> inc(b[0]);b[b[0]]:=q[ed];<br /> dec(ed);<br /> end;<br /> if b[0]>1 then work else begin<br /> fa[0,k]:=i;g[0,k]:=w[j];<br /> end;<br /> end;<br /> end;<br /> j:=next[j];<br /> end;<br /> while sk[tp+1]<>i do begin<br /> v[sk[tp]]:=false;dec(tp);<br /> end;<br />end;<br />procedure find(i:longint);<br />begin<br /> if d[i]>0 then exit;<br /> find(fa[0,i]);<br /> d[i]:=d[fa[0,i]]+1;<br />end;<br />begin<br /> assign(input,'path.in');reset(input);<br /> assign(output,'path.out');rewrite(output);<br /> readln(n,m,task);<br /> e:=1;<br /> for m:=1 to m do begin<br /> readln(i,j,k);<br /> inc(e); next[e]:=h[i];point[e]:=j;w[e]:=k;h[i]:=e;<br /> inc(e); next[e]:=h[j];point[e]:=i;w[e]:=k;h[j]:=e;<br /> end;<br /> dfs(1);<br /> d[1]:=1;<br /> for i:=1 to n do begin<br /> find(i);<br /> if d[i]>md then md:=d[i];<br /> end;<br /> md:=trunc(ln(md-1)/ln(2)+1e-8);<br /> for j:=1 to md do<br /> for i:=1 to n do begin<br /> fa[j,i]:=fa[j-1,fa[j-1,i]];<br /> g[j,i]:=g[j-1,i]+g[j-1,fa[j-1,i]];<br /> end;<br /> for task:=1 to task do begin<br /> readln(i,j);<br /> if d[i]>d[j] then begin<br /> k:=i;i:=j;j:=k;<br /> end;<br /> k:=0;<br /> for l:=md downto 0 do<br /> if d[fa[l,j]]>=d[i] then begin<br /> k:=k+g[l,j];<br /> j:=fa[l,j];<br /> end;<br /> if i=j then begin<br /> writeln(k);continue;<br /> end;<br /> for l:=md downto 0 do<br /> if fa[l,i]<>fa[l,j] then begin<br /> k:=k+g[l,i]+g[l,j];<br /> i:=fa[l,i];j:=fa[l,j];<br /> end;<br /> if (f[i]=f[j])and(f[i]<>0) then<br /> k:=k+min(abs(p[i]-p[j]),s[f[i]]-abs(p[i]-p[j]))<br /> else<br /> k:=k+g[0,i]+g[0,j];<br /> writeln(k);<br /> end;<br /> close(input);close(output);<br />end. 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.