HNOI2012 礦場搭建(tarjan求點雙)

2021-08-28 08:40:34 字數 2061 閱讀 4181

煤礦工地可以看成是由隧道連線挖煤點組成的無向圖。為安全起見,希望在工地發生事故時所有挖煤點的工人都能有一條出路逃到救援出口處。於是礦主決定在某些挖煤點設立救援出口,使得無論哪乙個挖煤點坍塌之後,其他挖煤點的工人都有一條道路通向救援出口。

請寫乙個程式,用來計算至少需要設定幾個救援出口,以及不同最少救援出口的設定方案總數。

輸入檔案有若干組資料,每組資料的第一行是乙個正整數 n,表示工地的隧道數,接下來的 n 行每行是用空格隔開的兩個整數 s 和 t ,表示挖煤點 s 與挖煤點 t 由隧道直接連線。輸入資料以 0 結尾。

輸入檔案中有多少組資料,輸出檔案中就有多少行。每行對應一組輸入資料的結果。

其中第 i 行以 case i: 開始(注意大小寫,case 與 i 之間有空格,i 與 : 之間無空格,: 之後有空格),其後是用空格隔開的兩個正整數,第乙個正整數表示對於第 i組輸入資料至少需要設定幾個救援出口,第二個正整數表示對於第 i 組輸入資料不同最少救援出口的設定方案總數。

輸出格式參照以下輸入輸出樣例。

再點雙連通分量中,如果壞了其中乙個點,那麼剩下的點還是連通的,所以我們求一次點雙連通分量,再仔細觀察一下,如果乙個點雙中(非割點點數為 n

nn):

沒有割點,那麼顯然要兩個通道,共 cn2

c_n^2

cn2​

種選法。

有乙個割點,那麼在這個點雙中就要有乙個通道,共,有乙個割點,那麼在這個點雙中就要有乙個通道,共 n

nn 種選法。

有兩個或者兩個以上的割點,則不需要通道。

問題解決了,不過我可能是太弱了,統計割點數和非割點數寫掛了,我們其實可以把每個割點找出來,dfs 一遍,割點之間就是乙個點雙,另外相鄰的割點也屬於這個點雙。

#include

#include

#include

#include

using

namespace std;

int dfn[

10005

],low[

10005

],cp[

10005

],cnt=0;

int bcc[

10005

],num[

10005

],son[

10005

],c=0;

bool vis[

100005

],iscp[

100005];

int n,m,x,y,h[

100005

],tot=

0,cas=0;

struct edgee[

200005];

inline

void

add_edge

(int x,

int y)

stack<

int> s;

void

tarjan

(int x,

int fa)

else low[x]

=min

(low[x]

,dfn[e[i]

.x]);}

if(son[x]

>

1&&fa==

0)iscp[x]

=true;}

void

dfs(

int x)}}

intmain()

for(

int i=

1;i<=n;i++)if

(!dfn[i]

)tarjan

(i,0);

unsigned

long

long sum=

0,ans=1;

for(

int i=

1;i<=n;i++)}

if(c==

1)sum=

2,ans=n*

(n-1)/

2;printf

("case %d: "

,++cas)

;printf

("%llu %llu\n"

,sum,ans);}

}

HNOI2012 礦場搭建

題目鏈結 演算法 對於任何乙個聯通塊,如果坍塌的是乙個聯通塊中的割點的話,那麼分割成的兩個小聯通塊中必須保證各有乙個出口。我們考慮所有的割點將原圖分割成若干個小聯通塊接下來分類討論 1 小塊不與任何乙個割點相連,那我們需要在這裡設立兩個出口,以保證任何乙個出口坍塌後,還有乙個出口可用。2 小塊只與乙...

HNOI2012 礦場搭建

顯然需要求一下點雙 然後列舉每乙個點雙,考慮進行分類討論 如果這乙個聯通塊裡面只有這乙個點雙,也就是這個點雙裡面沒有割點,那麼我們至少需要建造兩個出口,才能保證能跑出去 因為有可能選的那個塌了 如果這個點雙裡面有乙個割點,那麼有兩種情況,一種是割點塌了,這樣我們需要選出1個點,或者割點沒塌,這樣我們...

HNOI2012 礦場搭建

其實是劉汝佳藍書上面的例題啦,wf2011的乙個題 首先我們可以發現,把割頂塗上是不優的。因為刪掉它之後,因此被和原圖斷掉的那一部分就沒有黑點了,它對不連通的分量產生不了任何貢獻。所以我們要先預處理出來點雙聯通分量的割頂,不塗割頂。其次,對於乙個雙聯通分量來講,我們到底要塗幾個呢?其實乙個就夠了,因...