• 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]=='')
                    {
                        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
    ",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("
    ");
                    */
                }
            }
            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]=='')
                    {
                        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个连通分量
    ",i,subnets[i]+1);
                    ans++;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    BZOJ1316——树上的询问(点分治)
    BZOJ2152——聪聪可可(点分治)
    POJ1741(点分治)
    POJ2104——K-th Number (主席树模板)
    USACO Training Section 5.1 Fencing the Cows 圈奶牛(凸包)
    POJ1269(直线之间的关系)
    NOIP2016——换教室(floyd+期望dp)
    POJ2187(旋转卡壳)
    POJ3348——Cows(求凸包)
    ZOJ1081(射线法判断点是否在多边形内部)
  • 原文地址:https://www.cnblogs.com/zufezzt/p/4694433.html
Copyright © 2020-2023  润新知