poj 1144 割点和桥
生活随笔
收集整理的這篇文章主要介紹了
poj 1144 割点和桥
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
割點: 對于一個無向的連通圖,如果刪除一個點u及其相關的邊,會是的新的圖不連通,那么點u就稱為圖G的一個割點。
? ?記得 ? 首先這個圖是 ?無向的 其次是連通的。
vis[]記錄的是節點v當前的訪問狀態:1表示在棧中,0表示未訪問,2表示已經訪問過了;
dfn[]記錄的是節點v被訪問時的深度。
low[] 記錄的是節點v 可以到達的點重 深度的最小值。(我之前對這個low的理解不好,現在應該是理解了,請指正)
在深度遍歷圖的過程中,記錄下每個節點的深度。對當前節點cur,以及和它相連的節點i,有來年兩種情況:
(1)i沒被訪問過,這是遞歸訪問i,并且用i可以到達的最早的祖先來更新cur的low值
? (2) i當前在棧中,這是說明圖中有一個環,用i的深度更新cur的low值
cur是割點的條件是 ?cur是根,并且有大于一個的子節點,或者cur不是根,且cur有一個兒子v是的low[v]>=dfn[cur].
(cur,i)是橋的條件:low[i]>dfn[cur].
這道題的輸入麻煩了一點。要好好處理,否則會錯,
#include<cstdio> #include<cstring> #include<iostream> using namespace std;const int v=150; int edge[v][v]; //圖的鄰接矩陣 int bridge[v][v],cut[v]; //是否是橋 ,是否是 割點 int low[v],dfn[v],vis[v];void cut_bridge(int cur,int father,int dep,int n) {vis[cur]=1;dfn[cur]=low[cur]=dep;int children=0;for(int i=1;i<=n;i++){if(edge[cur][i]){if(i!=father&&vis[i]==1){if(dfn[i]<low[cur] ) low[cur]=dfn[i];}if(vis[i]==0){cut_bridge(i,cur,dep+1,n);children++;if(low[i]<low[cur]) low[cur]=low[i];if((father==-1&&children>1)||(father!=-1&&low[i]>=dfn[cur])) cut[cur]=1;if(low[i]>dfn[cur]) bridge[cur][i]=bridge[i][cur]=1;}}}vis[cur]=2; }int main() {int n;while(scanf("%d",&n),n){memset(bridge,0,sizeof(bridge));memset(edge,0,sizeof(edge));memset(cut,0,sizeof(cut));memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0x3f3f3f3f,sizeof(low));int i;getchar();int temp;scanf("%d",&temp);while(temp){char c=getchar();while(c!='\n'){int m;scanf("%d",&m);edge[temp][m]=edge[m][temp]=1;c=getchar();}scanf("%d",&temp);}int ans=0;cut_bridge(1,-1,0,n); // 對于每個連通塊 取一個點x調用這個函數for(i=1;i<=n;i++)if(cut[i])ans++;printf("%d\n",ans);}return 0; }總結
以上是生活随笔為你收集整理的poj 1144 割点和桥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 1116 欧拉路
- 下一篇: hdu 4284 floyd+暴搜