簡單說一下就是給定乙個無向聯通圖。要求找到割點(割點:若將該點和關聯該點的邊去掉,圖的連通性發生改變),並把割點刪去。求聯通圖的數量及在每個聯通圖上的某乙個點放置乙個救生器材的方案數。
我們先要找割點。
找割點的方法其實和找割邊有異曲同工之妙。
從一點開始dfs該圖可以得到一棵dfs樹,設dfs開始的結點為根 rt
。 在dfs樹中:
1.對於根結點,若它有兩棵或兩棵以上的子樹,那麼根結點一定是割點。
證明:假設根結點不是割點,那麼當挖去根結點後,那麼一定存在兩棵子樹之間是聯通的,那麼這樣的話在dfs樹上它們應該是一棵樹,因此發生矛盾。
2.對於葉結點,一定不是割點。
證明:因為它的度數只有
1 ,因此刪去後不改變連通性,所以一定不是割點。
3.對於非根非葉結點
u,如果它的某棵子樹中有乙個點指向
u 的祖先,那麼
u一定不是割點,否則是割點。
證明:如果它的某棵子樹中有乙個點指向
u 的祖先,刪除 u後,
u 的子樹仍然與
u的祖先有連通性,因此不是割點。否則一定是割點。
對於葉結點和根結點很好處理。對於非葉非根結點,我們可以採用在tarjan找強聯通圖演算法中的 df
n[i]
和 lo
w[i]
來判斷是否有回邊。df
n[i]
儲存的是
i 點在dfs過程中被訪問先後次序的序號, lo
w[i]
儲存的是
i 點及其子樹聯通的 df
n最小的點。 若 l
ow[i
]>=df
n[i]
,則表示
i 及其子樹不能訪問到更早的結點,即沒有回邊,那麼
i就是割點。
當找到所有割點後,進行一次dfs找到連通塊的數量即可。放置的方案數即每個聯通塊點數的乘積。
#include
using
namespace
std;
typedef
long
long ll;
const
int maxn=1e5+7;
int dfn[maxn],low[maxn];
bool vis[maxn];
vector
adj[maxn];
bool ge[maxn]; //標記該點是否是割點
int id,rt;
void init(int _rt)
void tarjan(int u,int pre)
}//low[u]>=dfn[u]就表示非根節點u的子樹中沒有點訪問到u的祖先,即沒有回邊。
//若是根節點,只要它在dfs樹中有兩個或以上的子樹就是割點。
if((low[u]>=dfn[u]&&u!=rt)||(u==rt&&cnt>=2))
ge[u]=true;
}ll ans;
ll dfs(int u)
return res;
}int main()
tarjan(1,0);
ans=1;
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=1;i<=m;i++)
if(!vis[i]&&!ge[i])
printf("%d ",cnt);
cout
<< ans << endl;
}return
0;}
CCCC團體天梯賽練習題 排座位
時間限制 150 ms 記憶體限制 65536 kb 長度限制 8000 b 判題程式 standard 作者 陳越 布置宴席最微妙的事情,就是給前來參宴的各位賓客安排座位。無論如何,總不能把兩個死對頭排到同一張宴會桌旁!這個艱鉅任務現在就交給你,對任何一對客人,請編寫程式告訴主人他們是否能被安排同...
cccc練習題連續因子和N個數求和
本來我想的就是把所有因子列出來然後找第乙個連續最長的,但是坑還不少。1.資料12 2 3 4比12大,只能取2 3.2.我本來想優化,跳過連續的乙個串,但是這樣就跳過了其中的子串,而子串是可能的解。3.想優化只看開方以前的因子,事實證明別瞎優化。4.想暴力列舉所有因子,丫的超時。5.對於沒有其他因子...
藍橋杯練習題 入門訓練
序列求和 問題描述 求1 2 3 n的值。輸入格式 輸入包括乙個整數n。輸出格式 輸出一行,包括乙個整數,表示1 2 3 n的值。樣例輸入 4 樣例輸出 10 樣例輸入 100 樣例輸出 5050 資料規模與約定 1 n 1,000,000,000 這個題如果是累加計算提交會顯示超時,所以最好的方法...