題面
題解首先先對割點這個東西有乙個形象的理解。
乙個割點就是兩個或多個點雙的交,所以不能把它理解成「縮點後形成的樹」上的邊。
也可以理解成是乙個點雙的邊界且不能是圖的邊界,所以我認為割點並不是很優美。
兩個點雙之間,最多只有乙個割點(要不然就不叫割點了)
割點和橋的對比:
點雙要求嚴格,所以點雙都較小,所以割點好找。($low[y]>=dfn[x]$)(說一句,在此過程中,父邊能不能更新$low[x]$是不影響結果的)
邊雙要求不嚴格,所以邊雙比較大,所以割邊難找。($low[y]>dfn[x]$)(此過程中,顯然不能更新)
再說割點的求法(多年不寫我早已遺忘)
當$low[y]>=dfn[x]$時,應該彈棧,直到彈到$y$,再把$x$「算到」這個點雙裡面(如果彈棧到$x$,先搜的下面的已經判定和$x$形成乙個點雙的部分,就被劃歸為這個點雙里了,但其實,這些部分應該和$x$和$x$上面的點是乙個點雙里的)
這樣求點双是沒有要特判的部分的。
但是求割點的時候,由於不能是邊界上的點,所以當$x$是根時,要多維護乙個$rs$,記錄$x$的不相交的兒子總共有多少個,如果$rs<=1$,就出現了烏龍,$x$不是割點,因為$x$沒有上面的部分。
回到我們這題
我們把原圖中的乙個點雙建乙個點,乙個割點建乙個點,乙個割點向它所在的點雙們連邊,這樣就形成了一顆樹,並且割點所代表的點,他們的度數不為$1$,如果看做無根樹 ,他們一定不在邊界上,在邊界上的點一定是點雙代表的點。
我們只考慮在非割點上建出口的情況,對於度為$1$的代表點雙的點,我們必須在其中任意乙個非割點建乙個出口。
對於度$>=2$的代表點雙的點,我們可以通過它走到其他葉子點上,所以不用建。
還有一種情況是特殊考慮的,就是整個聯通塊縮成乙個孤立的點,也就是沒有割點,那我們任選兩個建出口(乙個塌了走另外乙個)
那如果考慮,可以在割點上建出口,答案會不會更優呢?
本來度數就$>=2$的點不需要建,我們不考慮。
葉子點雙是必須建的,如果我們在割點上建,可以乙個當多個使用啊(滑稽),但其實這樣是錯誤的。因為如果乙個葉子點雙,只在割點上建,那麼割點塌了就沒的逃了。。。。。
#include#include#include
#include
#include
#include
#define ll long long
#define n 550
#define ri register int
using
namespace
std;
intdfn[n],low[n],cut[n];
intn,num,ctc,cc,t;
vector
to[n],c1[n],c2[n];
stack
s;ll ans1,ans2;
void add_edge(int u,int
v) void tarjan(int x,int
ff)
if (cut[x]) ++ctc; else ++num;
c1[x].push_back(ctc); c2[x].push_back(num);}}
else low[x]=min(low[x],dfn[y]);
} if (x==ff && rs<=1
)
for (ri i=0;i)
else
if (c1[x][i]==1
) }
}int
main()
for (ri i=1;i<=n;i++) if (!dfn[i]) tarjan(i,i);
printf(
"case %d: %lld %lld\n
",++t,ans1,ans2);
} return0;
}
HNOI2012 礦場搭建
題目鏈結 演算法 對於任何乙個聯通塊,如果坍塌的是乙個聯通塊中的割點的話,那麼分割成的兩個小聯通塊中必須保證各有乙個出口。我們考慮所有的割點將原圖分割成若干個小聯通塊接下來分類討論 1 小塊不與任何乙個割點相連,那我們需要在這裡設立兩個出口,以保證任何乙個出口坍塌後,還有乙個出口可用。2 小塊只與乙...
HNOI2012 礦場搭建
顯然需要求一下點雙 然後列舉每乙個點雙,考慮進行分類討論 如果這乙個聯通塊裡面只有這乙個點雙,也就是這個點雙裡面沒有割點,那麼我們至少需要建造兩個出口,才能保證能跑出去 因為有可能選的那個塌了 如果這個點雙裡面有乙個割點,那麼有兩種情況,一種是割點塌了,這樣我們需要選出1個點,或者割點沒塌,這樣我們...
HNOI2012 礦場搭建
其實是劉汝佳藍書上面的例題啦,wf2011的乙個題 首先我們可以發現,把割頂塗上是不優的。因為刪掉它之後,因此被和原圖斷掉的那一部分就沒有黑點了,它對不連通的分量產生不了任何貢獻。所以我們要先預處理出來點雙聯通分量的割頂,不塗割頂。其次,對於乙個雙聯通分量來講,我們到底要塗幾個呢?其實乙個就夠了,因...