1. 程式人生 > 實用技巧 >統計圖中連通塊的數量以及連通塊中點的個數(遞迴和非遞迴)

統計圖中連通塊的數量以及連通塊中點的個數(遞迴和非遞迴)

/*
上一道是根據割點判斷可以割出多少個連通塊來
對於每個圖,割某個點,產生連通塊的數量最大是多少.
一個割點編號對應一個剩餘連通塊的最大值.統計有幾個最大值

how to 求連通塊,怎麼求每個連通塊中點的個數

對v-dcc縮點之後,每個v-dcc的度數就是這個v-dcc連著幾個割點

分別看每個連通塊,設連通塊中點的個數是cnt
如果連通塊中沒有割點,那麼ans= c(cnt,2);
如果連通塊中有割點
1.如果有n個v-dcc的度數為1,那麼建n的出口
2.如果v-dcc的度數為2,說明這個v-dcc連線著兩個割點,無論是v-dcc中的點還是割點坍塌,一定可以通過
別的點逃脫
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int N=2*510,M=510;

int h[N],e[M],ne[M],idx;
int low[N],dfn[N],tim;
int d[N];//每個v-dcc的度數
long long ans=0;

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

int cnt;
vector<int>v[N];
int num[N];//儲存連通塊中點的個數
void dfs(int u)
{
    dfn[u]=1;
    v[cnt].push_back(u);//節點u是第cnt個連通塊中的點
    int sum=0;//必須從0開始,最後再加1
    // num[cnt]++;
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(!dfn[j])
            sum++,dfs(j);
    }
    num[cnt]+=sum;//+=
}
int main()
{
    int m,flag=1;
    while(cin>>m,m)
    {
        int n=-1;
        idx=0;
        memset(h,-1,sizeof h);
        while(m--)
        {
            int a,b;cin>>a>>b;
            n=max(a,n);
            n=max(b,n);
            add(a,b);
            add(b,a);
        }
        // cout<<n<<endl;
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                cnt++,dfs(i);
        cout<<cnt<<endl;//連通塊的數量
        
        for(int i=1;i<=cnt;i++)
            cout<<num[i]<<endl;
        cout<<"---"<<endl;
        for(int i=1;i<=cnt;i++)
            cout<<v[i].size()<<endl;
    }
}