日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POJ 1523 SPF (割点 点双连通分量)

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ 1523 SPF (割点 点双连通分量) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:求出割點以及除去割點后的連通分量的數量(附帶求出了點雙連通分量(塊)) [求割點]對圖深度優先搜索,定義DFS(u)為u在搜索樹(以下簡稱為樹)中被遍歷到的次序號。定義Low(u)為u或u的子樹中能通過非父子邊追溯到的最早的節點,即DFS序號最小的節點。根據定義,則有:Low(u)=Min {DFS(u),DFS(v)|(u,v)為后向邊(等價于DFS(v)<DFS(u)且v不為u的父親節點),Low(v)|(u,v)為樹枝邊} [條件]一個頂點u是割點,當且僅當滿足(1) u為樹根,且u有多于一個子樹。或(2) u不為樹根,且滿足存在(u,v)為樹枝邊(即u為v在搜索樹中的父親),使得DFS(u)<=Low(v)。 [除去點后的連通分量的]:對于(1)的割點,數量為子樹的數量;(2)的數量就是滿足條件的v的個數+1(它的父親節點). [求點雙連通分支]對于點雙連通分支,實際上在求割點的過程中就能順便把每個點雙連通分支求出。建立一個棧,存儲當前雙連通分支,在搜索圖時,每找到一條樹枝邊或后向邊,就把這條邊加入棧中。如果遇到某時滿足DFS(u)<=Low(v),說明u是一個割點,同時把邊從棧頂一個個取出,直到遇到了邊(u,v),取出的這些邊與其關聯的點,組成一個點雙連通分支。割點可以屬于多個點雙連通分支,其余點和每條邊只屬于且屬于一個點雙連通分支。 ? #include #include #include #include #include #include #include #include #include #include #include #include #define MID(x,y) ((x+y)>>1) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std;const int MAXE = 1000005; const int MAXV = 1005; struct node{int u, v;int next; }arc[MAXE]; int cnt, head[MAXV]; void init(){cnt = 0;mem(head, -1); } void add(int u, int v){arc[cnt].u = u;arc[cnt].v = v;arc[cnt].next = head[u];head[u] = cnt++;arc[cnt].u = v;arc[cnt].v = u;arc[cnt].next = head[v];head[v] = cnt++;return ; }int id, dfn[MAXV], low[MAXV]; //時間戳 int bcc_num; //點雙聯通分量標號 vector bcc[MAXV]; //因為割點可以屬于多個雙聯通分量,所以用數組存儲每個雙聯通分量的節點而不是用標號數組表示每個節點所屬的雙聯通分量 stack st; //棧中存著樹枝邊或后向邊 int res[MAXV]; //本題所求答案,即割點連接的雙聯通分量個數,樹根是子樹個數,非樹根是子樹個數+1. void addbcc(int bcc_num, int u){for (int i = 0; i < (int)bcc[bcc_num].size(); i ++){if (bcc[bcc_num][i] == u)return ;}bcc[bcc_num].push_back(u); } void tarjan(int u, int father){dfn[u] = low[u] = ++id;int child = 0;for (int i = head[u]; i != -1; i = arc[i].next){int v = arc[i].v;if (v == father) continue;if (dfn[v] < dfn[u]){ //避免正向邊st.push(i);if (!dfn[v]){ //樹枝邊child ++; //注意這里統計兒子節點時不要寫在if外面tarjan(v, u);low[u] = min(low[u], low[v]);if (dfn[u] <= low[v]){bcc_num ++;res[u] ++; //非樹根節點連接的雙聯通分量個數while(!st.empty()){int su = arc[st.top()].u;int sv = arc[st.top()].v;st.pop();addbcc(bcc_num, su);addbcc(bcc_num, sv);if((su == u && sv == v) || (su == v && sv == u)){break;}}}}else{ //后向邊low[u] = min(low[u], dfn[v]);}}}//統計割點連接的雙聯通分量個數if (father == 0){if (child >= 2){ //樹根大于一個子樹才是割點res[u] = child;}elseres[u] = 0;}else if (res[u] > 0) //非樹根除了子樹個數還要加上父親節點res[u] ++; } void solve(){id = bcc_num = 0;mem(dfn, 0);mem(low, 0);mem(res, 0);while(!st.empty())st.pop();tarjan(1, 0); } int main(){int u, v;int t = 0;while(scanf("%d", &u) == 1){init();++ t;if (u == 0)break;if (t > 1)puts("");scanf("%d", &v);add(u, v);while(scanf("%d", &u) == 1){if (u == 0)break;scanf("%d", &v);add(u, v);}solve();bool flag = 0;printf("Network #%d\n", t);for (int i = 1; i <= MAXV; i ++){if (res[i] > 0){printf(" SPF node %d leaves %d subnets\n", i, res[i]);flag = 1;}}if (!flag){puts(" No SPF nodes");}}return 0; }

轉載于:https://www.cnblogs.com/AbandonZHANG/archive/2013/05/30/4114026.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的POJ 1523 SPF (割点 点双连通分量)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。