• 【POJ 1523】SPF(割点)


     儿子数大于1的树根或者 Low[v] >= DFN[u]的非树根节点v 就是割点。

    #include <cstdio>
    #include <cstring>
    
    const int N = 1001;
    const int M = 1000010;
    struct Edge
    {
        int to,next;
        bool cut;//是否为桥的标记
    }edge[M];
    int head[N],tot;
    int Low[N],DFN[N],Stack[N];
    int Index,top;
    bool Instack[N];
    bool cut[N];//是否为割点
    int add_block[N];//删除一个点后增加的连通块
    int bridge;
    int va[N];
    void addedge(int u,int v)
    {
        edge[tot].to = v;edge[tot].next =head[u];edge[tot].cut = false;
        head[u] = tot++;
    }
    void Tarjan(int u,int pre)
    {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        int son = 0;
        for(int i = head[u];~i;i = edge[i].next)
        {
            v = edge[i].to;
            if(v == pre)continue;
            if( !DFN[v] )
            {
                son++;
                Tarjan(v,u);
                if(Low[u] > Low[v])Low[u] = Low[v];
                //
                if(Low[v] > DFN[u])
                {
                    bridge++;
                    edge[i].cut = true;
                    edge[i^1].cut = true;
                }
                if(u != pre && Low[v] >= DFN[u])//不是树根
                {
                    cut[u] = true;
                    add_block[u]++;
                }
            }
            else if( Low[u] > DFN[v])
                Low[u] = DFN[v];
        }
        //树根,分支数大于1
        if(u == pre && son > 1)cut[u] = true;
        if(u == pre)add_block[u] = son - 1;
        Instack[u] = false;
        top--;
    }
    void solve(){
        memset(DFN,0,sizeof DFN);
        memset(Instack,0,sizeof Instack);
        memset(add_block,0,sizeof add_block);
        memset(cut,false,sizeof cut);
        Index=top=0;
        int cnt=0,ans=0;
        for(int i=1;i<N;i++)
            if(va[i]&&!DFN[i]){
                Tarjan(i, i);
                cnt++;
            }
        for(int i=1;i<N;i++)
            if(cut[i]){
                ans++;
                printf("  SPF node %d leaves %d subnets
    ",i,cnt+add_block[i]);
            }
        if(ans==0)
            puts("  No SPF nodes");
        
    }
    void init(){
        memset(head,-1,sizeof head);
        memset(va,0,sizeof va);
        tot=0;
    }
    int main(){
        int u,v,cas=0;
        init();
        while(~scanf("%d",&u)){
            if(u==0&&tot){
                printf("Network #%d
    ",++cas);
                solve();
                init();
                puts("");
                continue;
            }
            scanf("%d",&v);
            addedge(u,v);
            addedge(v,u);
            va[u]=va[v]=1;
        }
    }

      

  • 相关阅读:
    字符个数统计
    面试题——字符的左右移动
    5. Longest Palindromic Substring
    Linux- AWS之EC2大数据集群定时开关机
    Openldap- 大机群身份验证服务
    Linux- 自动备份MySQL数据库脚本
    Linux- 运维
    JAVA- 切换默认的Java
    HIVE- 新建UDF范例
    Hadoop- 集群启动详解
  • 原文地址:https://www.cnblogs.com/flipped/p/5759362.html
Copyright © 2020-2023  润新知