題意:煤礦工地可以看成是由隧道連線挖煤點組成的無向圖。為安全起見,希望在工地發生事故時所有挖煤點的工人都能有一條出路逃到救援出口處。於是礦主決定在某些挖煤點設立救援出口,使得無論哪乙個挖煤點坍塌之後,其他挖煤點的工人都有一條道路通向救援出口。
請寫乙個程式,用來計算至少需要設定幾個救援出口,以及不同最少救援出口的設定方案總數。
思路:如果塌的不是割點,那麼不影響圖的連通性,也就不影響其他人的逃生。考慮最簡單的情況:整張圖沒有割點,那麼需要幾個出口?1個?不是。如果設的出口恰好塌了就涼了。所以多乙個備用的,這個情況要2個。如果有割點呢?我們考慮v1-g-v2,g是割點,如果不是g塌了,那麼還是乙個連通圖,如果塌了g,那麼分成兩個連通圖。因此g塌是最差情況。這時需要在v1和v2各設乙個出口。
因此我們用割點將圖割開,分別統計每乙個連通塊,每個連通塊需要1個出口,有連通塊大小個放法。
如果
v1-g-v2
|
v3-g2-v4 (g和g2是割點)
這樣呢?v3連了2個割點,不管哪個塌了,v3都可以跑到另一邊,實際上塌不塌對v3沒有任何影響,即,乙個連通塊連了2個及以上割點,就不考慮它。
#include
using
namespace std;
const
int maxn=
600;
typedef
long
long ll;
int t,n,m,pre[maxn]
,iscut[maxn]
,dfs_clock,block;
vector<
int> g[maxn]
;int vis[maxn]
,cal[maxn]
,dag,sz;
intdfs
(int u,
int fa)
else
if(pre[v]
&&v!=fa)lowu=
min(lowu,pre[v]);
}if(fa==-1
&& child==
1)iscut[u]=0
;return lowu;
}void
dfs2
(int u)
}int
main()
for(
int i=
1;i<=n;i++)if
(!pre[i]
)dfs
(i,-1)
; ll ans1=
0,ans2=1;
for(
int i=
1;i<=n;i++)if
(!vis[i]
&&!iscut[i])}
if(block>1)
printf
("case %d: %lld %lld\n"
,++t,ans1,ans2)
;else
printf
("case %d: %lld %lld\n"
,++t,2,
(ll)n*
(n-1)/
2);}
return0;
}```
洛谷 P3225 HNOI2012 礦場搭建
邊數n 500的挖煤點,需要設定盡量少的逃生出口,使得某個煤礦倒塌後,其他挖煤點的工人仍然可以通過某條路徑到達逃生出口,並給出逃生出口最少設定數量與方案數 多組資料 倒塌一座後 這一點令人想到割點 割點的倒塌會增加連通塊數量,產生隔斷 所以本題中顯然割點是比較重要的一種分析。先用tarjan跑出割點...
洛谷 P3225 HNOI2012 礦場搭建
煤礦工地可以看成是由隧道連線挖煤點組成的無向圖。為安全起見,希望在工地發生事故時所有挖煤點的工人都能有一條出路逃到救援出口處。於是礦主決定在某些挖煤點設立救援出口,使得無論哪乙個挖煤點坍塌之後,其他挖煤點的工人都有一條道路通向救援出口。請寫乙個程式,用來計算至少需要設定幾個救援出口,以及不同最少救援...
洛谷 P3225 HNOI2012 礦場搭建
在大家都在努力的考試的最後半個小時裡,不會做考試題的我來水乙個題解。煤礦工地可以看成是由隧道連線挖煤點組成的無向圖。為安全起見,希望在工地發生事故時所有挖煤點的工人都能有一條出路逃到救援出口處。於是礦主決定在某些挖煤點設立救援出口,使得無論哪乙個挖煤點坍塌之後,其他挖煤點的工人都有一條道路通向救援出...