zoukankan      html  css  js  c++  java
  • POJ 1523 SPF 割点与桥的推断算法-Tarjan

    题目链接:

    POJ1523







    题意:

    问一个连通的网络中有多少个关节点,这些关节点分别能把网络分成几部分



    题解:

    Tarjan 算法模板题


    顺序遍历整个图,能够得到一棵生成树:

    树边:可理解为在DFS过程中訪问未訪问节点时所经过的边。也称为父子边

    回边:可理解为在DFS过程中遇到已訪问节点时所经过的边。也称为返祖边、后向边

    对根节点u,若其有两棵或两棵以上的子树。则该根结点u为割点。

    对非叶子节点u(非根节点)。若其子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与u的子树的节点不再连通;则节点u为割点。


    // 当(u,v)为树边且low[v]>dfn[u]时,表示v节点仅仅能通过该边(u,v)与u连通,那么(u,v)即为割边。

    用一个数组保存每一个节点的子树个数就可以



    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define maxn 1050
    using namespace std;
    int dfn[maxn],low[maxn];          //dfs序  和子树连接的最小节点
    int vis[maxn];
    vector<int>edge[maxn];   
    int child[maxn];
    int num,son;
    void init()
    {
        memset(vis,0,sizeof(vis));
        memset(child,0,sizeof(child));
        vis[1]=1;
        num=0;
        son=0;
    }
    void Tarjan(int u)
    {
        dfn[u]=low[u]=++num;
        vis[u]=1;
        for(int i=0; i<edge[u].size(); i++)
        {
            int v=edge[u][i];
            if(!vis[v])
            {
                Tarjan(v);
                low[u]=min(low[u],low[v]);
                if(dfn[u]<=low[v])       //得到子树
                {
                    if(u!=1)
                        child[u]++;
                    else
                        son++;
                }
            }
            else low[u]=min(low[u],dfn[v]);
        }
    }
    int main()
    {
    //    freopen("in.txt","r",stdin);
        int a,b;
        int Case=1;
        while(1)
        {
            while(scanf("%d",&a)&&a)
            {
    
                scanf("%d",&b);
                edge[a].push_back(b);
                edge[b].push_back(a);
            }
            init();
    
            Tarjan(1);
    //        for(int i=1;i<=5;i++)
    //        cout<<dfn[i]<<" "<<low[i]<<endl;
            if(Case>1)
                cout<<endl;
            printf("Network #%d
    ",Case++);
            int flag=1;
            child[1]=son-1;
            for(int i=1; i<=1000; i++)
                if(child[i]>0)
                {
                    flag=0;
                    printf("  SPF node %d leaves %d subnets
    ",i,child[i]+1);
                }
            if(flag)
                cout<<"  No SPF nodes"<<endl;
    
    
            for(int i=1; i<=1000; i++)
                edge[i].clear();
            scanf("%d",&a);
            if(a==0)
                break;
            scanf("%d",&b);
            edge[a].push_back(b);
            edge[b].push_back(a);
        }
        return 0;
    }
    


  • 相关阅读:
    Thread的run方法和start方法
    35. Search Insert Position
    Error:(1, 1) java: 非法字符: 'ufeff'
    final修饰的变量是引用不可变,还是对象不可变
    数组与练习
    java反射机制【转】
    Socket
    面向对象的设计原则和设计模式
    多线程
    为什么有时候修改了css文件,页面的样式却没有改变?
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6714371.html
Copyright © 2011-2022 走看看