洛谷 P3225 HNOI2012 礦場搭建

2021-10-02 18:16:23 字數 3162 閱讀 3192

邊數n<=500的挖煤點,需要設定盡量少的逃生出口,使得某個煤礦倒塌後,其他挖煤點的工人仍然可以通過某條路徑到達逃生出口,並給出逃生出口最少設定數量與方案數

多組資料

倒塌一座後…這一點令人想到割點(割點的倒塌會增加連通塊數量,產生隔斷),所以本題中顯然割點是比較重要的一種分析。

先用tarjan跑出割點,發現把出口安放到割點上不是最優的(割點的倒塌會使連通塊增加+出口減少,不利)

所以就要分析除割點外的其他部分,如何安放出口。

不難想到,先把割點刪去可以造成一系列無割聯通塊:

方案①:在每個這樣的連通塊內安放兩個出口。

看似最優,其實有反例

如這種情況,無割圖123是刪去cut1,cut2得到的連通塊,不難想到比方案1中更優的情形:無割圖內不放出口,無割圖2和3內各乙個出口。

如果割點倒塌了乙個這樣仍能保證逃生

如果乙個出口倒塌,其內的人可以通過割點走到另乙個出口。

所以方案①不是最優

這樣,就發現出口的安排和這種無割圖的割點連線數有關。

無割圖可以考慮成一種縮點,判斷每乙個無割圖連線的割點數,不難發現:

方案②:

如果這個連通塊內本無割點,則只需要安排2個出口,為保證即便乙個倒塌,其他也能逃生,cn2

c_^2

cn2​

種安排如果乙個無割圖連線著乙個割點,其內只需安排乙個出口,n種安排

無割圖連線2個及以上割點,不需安排出口

不難想到,已知割點後再一次dfs,處理出每乙個塊的size及割點連線數,用組合數學即可計算出種數

#include

"cstdlib"

#include

#include

#include

#include

#include

#include

using

namespace std;

vector<

int> g[

510]

;//i為頂點,g[i]為從其延伸的邊集合

int dfs_clock =0;

//時間戳

int pre[

510]

;//每個節點被遍歷到時的時間戳

int iscut[

510]

;//記錄這個點是不是割點

int low[

510]

;// low[u]表示dfs樹中u及其後代經過單線能連回的最早祖先的pre值

intdfs

(int u,

int fa)

//處理u節點的bfs,其父為fa

else

if(pre[v]

< pre[u]

&& v != fa)

//v已被訪問過,且不是u的父親鄰居(u連出的這條邊是反向邊)}if

(fa ==

0&& child ==

1)iscut[u]=0

;//根節點且只有乙個子,這個根不是割點,2+個子節點則是

low[u]

= lowu;

return lowu;

}int id[

510]

;//刪去割點後,其餘元素屬於的連通塊編號

int siz[

510]

;//除去割點後,剩餘連通塊的元素個數

int cutnum[

510]

;//上面這種連通塊與多少割點相連

void

chunk

(int s,

int num)

//當前節點,當前節點所屬連通塊

else

chunk

(cur, num);}

}}intmax

(int

&a,int

&b,int

&c)else

}int

main()

for(

int i =

1; i <= n; i++

)//iscut[u]==1表示是割點

int cnt =0;

for(

int i =

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

long

long ans =1;

int c =0;

//安放個數

for(

int i =

1; i <= cnt; i++

)//本身是個無割點連通塊

else

if(cutnum[i]==1

)//連線著乙個割點的無割圖

else ans *=1

;//連線著》=2個割點的無割圖

} cout <<

"case "

<< o <<

": "

<< c <<

" "<< ans<

for(

int i =

1; i <= n; i++

)g[i]

.clear()

;memset

(low,0,

510*

sizeof

(int))

;memset

(pre,0,

510*

sizeof

(int))

;memset

(iscut,0,

510*

sizeof

(int))

;memset

(id,0,

510*

sizeof

(int))

;memset

(siz,0,

510*

sizeof

(int))

;memset

(cutnum,0,

510*

sizeof

(int))

; dfs_clock =0;

//初始化過程

}return0;

}

洛谷P3225 HNOI2012 礦場搭建

題意 煤礦工地可以看成是由隧道連線挖煤點組成的無向圖。為安全起見,希望在工地發生事故時所有挖煤點的工人都能有一條出路逃到救援出口處。於是礦主決定在某些挖煤點設立救援出口,使得無論哪乙個挖煤點坍塌之後,其他挖煤點的工人都有一條道路通向救援出口。請寫乙個程式,用來計算至少需要設定幾個救援出口,以及不同最...

洛谷 P3225 HNOI2012 礦場搭建

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

洛谷 P3225 HNOI2012 礦場搭建

在大家都在努力的考試的最後半個小時裡,不會做考試題的我來水乙個題解。煤礦工地可以看成是由隧道連線挖煤點組成的無向圖。為安全起見,希望在工地發生事故時所有挖煤點的工人都能有一條出路逃到救援出口處。於是礦主決定在某些挖煤點設立救援出口,使得無論哪乙個挖煤點坍塌之後,其他挖煤點的工人都有一條道路通向救援出...