统计图中连通块的数量以及连通块中点的个数(递归和非递归)

/*
上一道是根据割点判断可以割出多少个连通块来
对于每个图,割某个点,产生连通块的数量最大是多少.
一个割点编号对应一个剩余连通块的最大值.统计有几个最大值

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;
    }
}
posted @ 2020-12-08 21:35  30天CF上蓝!!!  阅读(305)  评论(0编辑  收藏  举报