hihoCoder #1190 : 連通性·四(點的雙連通分量模板)
描述
小Hi和小Ho從約翰家回到學校時,網絡所的老師又找到了小Hi和小Ho。
老師告訴小Hi和小Ho:之前的分組出了點問題,當服務器(上次是連接)發生宕機的時候,在同一組的服務器有可能連接不上,所以他們希望重新進行一次分組。這一次老師希望對連接進行分組,並把一個組內的所有連接關聯的服務器也視為這個組內的服務器(註意一個服務器可能屬於多個組)。
這一次的條件是對於同一個組滿足:當組內任意一個服務器宕機之後,不會影響組內其他服務器的連通性。在滿足以上條件下,每個組內的邊數量越多越好。
比如下面這個例子,一共有6個服務器和7條連接:
其中包含3個組,分別為{(1,2),(2,3),(3,1)},{(4,5),(5,6),(4,6)},{(3,4)}。對{(1,2),(2,3),(3,1)}而言,和該組邊相關聯的有{1,2,3}三個服務器:當1宕機後,仍然有2-3可以連接2和3;當2宕機後,仍然有1-3可以連接1和3;當3宕機後,仍然有1-2可以連接1和2。
老師把整個網絡的情況告訴了小Hi和小Ho,希望小Hi和小Ho統計一下一共有多少個分組。
提示:點的雙連通分量
輸入
第1行:2個正整數,N,M。表示點的數量N,邊的數量M。1≤N≤20,000, 1≤M≤100,000
第2..M+1行:2個正整數,u,v。第i+1行表示存在一條邊(u,v),編號為i,連接了u,v兩臺服務器。1≤u<v≤N
保證輸入所有點之間至少有一條連通路徑。
輸出
第1行:1個整數,表示該網絡的連接組數。
第2行:M個整數,第i個數表示第i條連接所屬組內,編號最小的連接的編號。比如分為{(1,2)[1],(2,3)[3],(3,1)[2]},{(4,5)[5],(5,6)[7],(4,6)[6]},{(3,4)[4]},方括號內表示編號,則輸出{1,1,1,4,5,5,5}。
代碼
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5#include<stack> 6 #include<algorithm> 7 using namespace std; 8 const int N=2e4+5; //最大點數 9 const int M=1e5+5; //最大邊數 10 11 struct node{ 12 int id,to; 13 node(int id,int to):id(id),to(to){} 14 }; 15 vector<node>v[N]; 16 stack<int>sk; 17 int cnt,num; 18 int low[N],dfn[N],fa[M],mp[M]; 19 //fa[i]為第i條邊所屬的點雙連通分量編號 20 //mp[i]為編號為i的點雙連通分量裏編號最小的編號 21 //一定註意fa和mp的範圍是邊數的範圍M,不是點數範圍N 22 void tarjan(int u,int f){ 23 low[u]=dfn[u]=++cnt; 24 for(int i=0;i<v[u].size();i++){ 25 int t=v[u][i].to; 26 int id=v[u][i].id; 27 if(t==f) continue; 28 if(!dfn[t]){ //樹邊 29 sk.push(id); //邊入棧 30 tarjan(t,u); 31 low[u]=min(low[u],low[t]); 32 if(dfn[u]<=low[t]){ 33 num++; 34 while(!sk.empty()){ 35 int cur=sk.top(); 36 sk.pop(); 37 fa[cur]=num; 38 if(mp[num]==0||mp[num]>cur) 39 mp[num]=cur; 40 if(cur==id) break; 41 } 42 } 43 } 44 else if(dfn[t]<dfn[u]){//回邊 45 low[u]=min(low[u],dfn[t]); 46 sk.push(id); //邊入棧 47 } 48 } 49 } 50 51 int main(){ 52 int n,m; 53 scanf("%d%d",&n,&m);; 54 for(int i=1;i<=m;i++){ 55 int a,b; 56 scanf("%d%d",&a,&b); 57 v[a].push_back(node(i,b)); 58 v[b].push_back(node(i,a)); 59 } 60 tarjan(1,-1); 61 printf("%d\n",num); 62 for(int i=1;i<=m;i++){ 63 printf("%d%c",mp[fa[i]],i==m?‘\n‘:‘ ‘); 64 } 65 return 0; 66 }
hihoCoder #1190 : 連通性·四(點的雙連通分量模板)