POJ 1523 (割点+连通分量)

题目链接: http://poj.org/problem?id=1523

题目大意:连通图,找图中割点,并计算切除该割点后,图中的连通分量个数。

解题思路

POJ的数据很弱。

Tarjan法求割点。

pre数组,记录这个点的dfs时间位置。

割点的条件是lowv>=pre[u], 即子点比父点先dfs,这时候父点就没有意义了,切掉父点连通分量数肯定会增加。

同时注意特判只有两个点的情况,这时候是不可能出现割点的。

 

求切除割点后的联通分量数:

从割点出发,把图dfs一遍,如果u=割点,那么对于每个子点v,block++

原理就是,切掉割点后,所有与其连接子点都要受到影响,统计第一次访问的子点v的block即可。

 

#include "cstdio"

#include "vector"

#include "string"

#include "iostream"

#include "cstring"

using namespace std;

#define maxn 1005

struct Edge

{

    int next,to;

}e[maxn*2];

int pre[maxn],dfs_clock,block,head[maxn],tol;

bool cut[maxn],vis[maxn];

void addedge(int u,int v)

{

    e[tol].to=v;

    e[tol].next=head[u];

    head[u]=tol++;

}

int dfs(int u,int fa)

{

    int lowu=pre[u]=++dfs_clock;

    int child=0;

    for(int i=head[u];i!=-1;i=e[i].next)

    {

        int v=e[i].to;

        if(!pre[v])

        {

            child++;

            int lowv=dfs(v,u);

            lowu=min(lowu,lowv);

            if(lowv>=pre[u]) cut[u]=true;

        }

        else if(pre[v]<pre[u]&&v!=fa) lowu=min(lowu,pre[v]);

    }

    if(fa<0&&child==1) cut[u]=false;

    return lowu;

}

void check(int u,int fa)

{

    vis[u]=true;

    for(int i=head[u];i!=-1;i=e[i].next)

    {

        int v=e[i].to;

        if(!vis[v])

        {

            if(u==fa) block++;

            check(v,fa);

        }

    }

}

int main()

{

    //freopen("in.txt","r",stdin);

    int u,v,num=0,no=0;

    bool flag=false;

    memset(head,-1,sizeof(head));

    while(scanf("%d",&u)!=EOF)

    {

        if(!u)

        {

            if(!tol) break;

            printf("Network #%d\n",++no);

            for(int i=1;i<=num;i++) if(!pre[i]) dfs(i,-1);

            bool flag=false;

            for(int i=1; i<=num; i++)

                if(cut[i])

                {

                    flag=true;

                    check(i,i);

                    printf("  SPF node %d leaves %d subnets\n",i,block);

                    memset(vis,0,sizeof(vis));

                    block=0;

                }

            if(!flag) cout<<"  No SPF nodes"<<endl;

            memset(pre,0,sizeof(pre));

            memset(cut,false,sizeof(cut));

            memset(head,-1,sizeof(head));

            dfs_clock=0;num=0;tol=0;

            printf("\n");

        }

        else

        {

            scanf("%d",&v);num=max(num,max(u,v));

            addedge(u,v);

            addedge(v,u);

        }

    }

}

 

13424402 neopenx 1523 Accepted 216K 0MS C++ 2309B 2014-09-08 19:04:33

你可能感兴趣的:(poj)