【MT原創題 丘位元的煩惱】Hopcroft-Karp演算法、tarjan

來源:互聯網
上載者:User

題目H8OJ上有,這裡就不羅嗦了

題目不難,簡單講一下解法

先求個最大匹配,再把無向邊定向,匹配邊由x集->y集,非匹配邊由y集->x集,這樣定向了之後,任意一條從x集出發y集結束的路徑就對應了一條增廣路

求出這個圖的強連通分量,如果一條邊的兩個端點處於同一個分量內,那這條邊其實沒什麼影響力,刪了這條邊原圖仍然存在完備匹配

而如果這條邊的兩個端點不在一個分量內,那這條邊如果是匹配邊那就一定會被選,如果不是匹配邊那就一定不會被選

可是,由於這個題的資料規模比較重口味,N<=200000; M<=600000,傳統的匈牙利演算法已經無法勝任了,我們需要更NB的求最大匹配的演算法,這個演算法就是HK演算法

這個演算法名字看起來很唬人,實際上沒什麼

它的思想跟dinic有點像,大概就是每次先廣搜出一個距離標號,然後匈牙利的增廣過程就只找標號等於自己加一的點,一次標號多次增廣

可以證明增廣次數是O(sqrt(n))的,每次增廣的複雜度是O(m),總的複雜度就只有O(sqrt(n)*m)

一個細節:

由於要保證廣搜出來的路也是交錯軌,所以廣搜時x集的點只擴充y集的已蓋點,而y集的點只擴充它對應的那個匹配點,但距離標號還是要更新的

哎呀,感覺這裡有點說不清,參考代碼吧

program syj;<br />var<br /> n,m,t,i,j,k,e,st,ed:longint; ok:boolean;<br /> a,h,d,q,low,f:array[0..400005]of longint;<br /> next,point:array[0..1200005]of longint;<br /> aa,bb:array[0..600005]of longint;<br /> v:array[0..400005]of boolean;<br /> u:array[0..1200005]of boolean;<br />function find(i:longint):boolean;<br />var j,k:longint;<br />begin<br /> j:=h[i];<br /> while j<>0 do begin<br /> k:=point[j];<br /> if (d[k]=d[i]+1)and not v[k] then begin<br /> v[k]:=true;<br /> if (a[k]=0)or find(a[k]) then begin<br /> a[k]:=i;a[i]:=k;<br /> exit(true);<br /> end;<br /> end;<br /> j:=next[j];<br /> end;<br /> find:=false;<br />end;<br />procedure dfs(i:longint);<br />var j,k:longint;<br />begin<br /> inc(t); d[i]:=t;low[i]:=t;<br /> inc(ed); q[ed]:=i;<br /> v[i]:=true; j:=h[i];<br /> while j<>0 do begin<br /> if u[j] then begin<br /> j:=next[j];continue;<br /> end;<br /> u[j]:=true; k:=point[j];<br /> if d[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(d[k]<low[i]) then low[i]:=d[k];<br />// if low[k]>d[i] then g[j>>1]:=1+ord(i>k);<br /> j:=next[j];<br /> end;<br /> if d[i]=low[i] then<br /> while q[ed+1]<>i do begin<br /> v[q[ed]]:=false;f[q[ed]]:=i;<br /> dec(ed);<br /> end;<br />end;<br />begin<br /> assign(input,'cupid.in');reset(input);<br /> assign(output,'cupid.out');rewrite(output);<br /> readln(n,m);<br /> e:=1;<br /> for m:=1 to m do begin<br /> readln(j,k);<br /> aa[m]:=j;bb[m]:=k;<br /> inc(e); next[e]:=h[j];point[e]:=k+n;h[j]:=e;<br /> inc(e); next[e]:=h[k+n];point[e]:=j;h[k+n]:=e;<br /> end;<br /> ok:=true;<br /> while ok do begin<br /> st:=0;ed:=0;<br /> fillchar(d,sizeof(d),$FF);<br /> for i:=1 to n do<br /> if a[i]=0 then begin<br /> inc(ed);q[ed]:=i;d[i]:=0;<br /> end;<br /> while st<ed do begin<br /> inc(st);i:=q[st];<br /> if i<=n then begin<br /> j:=h[i];<br /> while j<>0 do begin<br /> k:=point[j];<br /> if d[k]=-1 then begin<br /> d[k]:=d[i]+1;<br /> if a[k]>0 then begin<br /> inc(ed);q[ed]:=k;<br /> end;<br /> end;<br /> j:=next[j];<br /> end;<br /> end else begin<br /> inc(ed);q[ed]:=a[i];d[a[i]]:=d[i]+1;<br /> end;<br /> end;<br /> ok:=false;<br /> fillchar(v,sizeof(v),0);<br /> for i:=1 to n do begin<br /> if a[i]=0 then<br /> ok:=find(i)or ok;<br /> end;<br /> end;<br />// for i:=1 to n+n do if a[i]=0 then writeln(i);<br /> for i:=1 to n+n do begin<br /> j:=h[i];<br /> while j<>0 do begin<br /> if (point[j]<>a[i])xor(i>n) then u[j]:=true;<br /> j:=next[j];<br /> end;<br /> end;<br /> ed:=0; t:=0;<br /> fillchar(v,sizeof(v),0);<br /> fillchar(d,sizeof(d),0);<br /> for i:=1 to n do if d[i]=0 then dfs(i);<br /> for i:=1 to m do<br /> if f[aa[i]]=f[bb[i]+n] then write(0) else<br /> if a[aa[i]]=bb[i]+n then write(1) else write(2);<br /> writeln;<br /> close(input);close(output);<br />end.<br /> 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.