POJ 1144 Network

求有几个割点。数据比较水,用了朴素方法。。。30ms。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

char s[1000000];
int n,u,v,tot,len,sum;
const int INF=0x7FFFFFFF;
const int MAXN=105;
vector<int>G[MAXN];
int fail[MAXN],flag[MAXN];

void DFS(int now)
{
    int i;
    for(i=0; i<G[now].size(); i++)
    {
        if(!flag[G[now][i]]&&!fail[G[now][i]])
        {
            flag[G[now][i]]=1;
            DFS(G[now][i]);
        }
    }
}

int main()
{
    int i,ii;
    while(~scanf("%d",&n)&&n)
    {
        for(i=0; i<=n; i++) G[i].clear();
        memset(flag,0,sizeof(flag));
        memset(fail,0,sizeof(fail));
        while(gets(s))
        {
            if(strcmp(s,"0")==0) break;
            len=strlen(s);
            u=INF;
            sum=0;
            for(i=0; i<=len; i++)
            {
                if(s[i]==' '||s[i]=='\0')
                {
                    if(u==INF) u=sum,sum=0;
                    else
                    {
                        v=sum,sum=0;
                        G[u].push_back(v);
                        G[v].push_back(u);
                    }
                }
                else sum=sum*10+s[i]-'0';
            }
        }


        memset(fail,0,sizeof(fail));
        
        int AAA,ans=0;
        for(ii=1; ii<=n; ii++)
        {
            fail[ii]=1;
            AAA=0;
            memset(flag,0,sizeof(flag));
            for(i=1; i<=n; i++)
            {
                if(fail[i]) continue;
                if(!flag[i])
                {
                    flag[i]=1;
                    DFS(i);
                    AAA++;
                }
            }
            if(AAA!=1) ans++;
            fail[ii]=0;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

 

下面是用Tarjan算法的。跑了500ms的样子。。。。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

const int INF=0x7FFFFFFF;
const int maxn=1111;//有多少个结点
vector<int>G[maxn];
int visited[maxn];//标记该节点有没有访问过
int node,edge;//顶点数目
int tmpdfn;//dfs过程中记录当前的深度优先搜索序数
int dfn[maxn];//记录每个顶点的深度优先搜索序数
int low[maxn];//每个顶点的low值,根据该值来判断是否是关节点
int son;//根结点的有多少个孩子,如果大于等于2,则根结点为关节点
int subnets[maxn];//记录每个结点(去掉该结点后)的连通分量的个数
char s[maxn];

/*以下是输出重连通分量用的*/
int top;
struct Edge
{
    int u,v;
    void output()
    {
        printf("%d-%d ",u,v);
    }
    bool cmp(Edge &t)
    {
        return ((u==t.u&&v==t.v)||(v==t.u&&u==t.v));
    }
};
Edge Stack[maxn];
int Flag[maxn][maxn];

void init()
{
    for(int i=0; i<maxn; i++) G[i].clear();
    low[1]=dfn[1]=1;
    tmpdfn=1;
    son=0;
    memset(visited,0,sizeof(visited));
    visited[1]=1;
    memset(subnets,0,sizeof(subnets));
}

void dfs(int u)
{
    for(int i=0; i<G[u].size(); i++)
    {
        int v=G[u][i];
        Edge t;

        /*将这条边压入栈顶*/
        if(!Flag[u][v])//没有入过栈
        {
            t.u=u;
            t.v=v;
            Stack[++top]=t;
            Flag[u][v]=Flag[v][u]=1;
        }

        if(!visited[v])
        {
            visited[v]=1;
            tmpdfn++;
            dfn[v]=low[v]=tmpdfn;
            dfs(v);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                if(u!=1) subnets[u]++;
                if(u==1) son++;
                /*
                printf("重连通分量:");
                while(1)
                {
                    if(top==-1) break;
                    Edge t1;
                    t1=Stack[top];
                    t1.output();
                    top--;
                    if(t1.cmp(t)) break;
                }
                printf("\n");
                */
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
}

int main()
{
    while(~scanf("%d",&node)&&node)//输入节点数量和边的数量
    {


        init();//初始化


        int len,u,v,sum;
        while(gets(s))
        {
            if(strcmp(s,"0")==0) break;
            len=strlen(s);
            u=INF;
            sum=0;
            for(int i=0; i<=len; i++)
            {
                if(s[i]==' '||s[i]=='\0')
                {
                    if(u==INF) u=sum,sum=0;
                    else
                    {
                        v=sum,sum=0;
                        G[u].push_back(v);
                        G[v].push_back(u);
                    }
                }
                else sum=sum*10+s[i]-'0';
            }
        }
        top=-1;//初始化 栈为空
        memset(Flag,0,sizeof(Flag));

        //DFS求解割点,点双连通分量,去掉一个个点之后有几个连通分量
        /*DFS过程中输出点双连通分量*/
        dfs(1);

        //计算根节点
        if(son>1) subnets[1]=son-1;

        int ans=0;

        /*输出割点*/
        for(int i=1; i<=node; i++)
            if(subnets[i])
                //printf("%d号节点是割点,删除之后有%d个连通分量\n",i,subnets[i]+1);
                ans++;
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2015-08-01 17:58  Fighting_Heart  阅读(167)  评论(0编辑  收藏  举报