zoukankan      html  css  js  c++  java
  • 图的割点 | | jzoj【P1230】 | | gdoi | |备用交换机

    写在前面:我真的不知道图的割点是什么。。。。

    看见ftp图论专题里面有个dfnlow的一个文档,于是怀着好奇的心情打开了这个罪恶的word文档,,然后就开始漫长的P1230的征讨战。。。。

    图的割点是这样的:

      path1=暴力      

        枚举每一个点,如果去掉这个点就可以使图断开,那么这个点就是割点(时间复杂度O(N(N+M)))

      path2=tarjan     

        从任意一个点开始遍历,记录遍历的顺序,然后对正在遍历的点进行一次深度优先遍历,但是此次遍历不允许经过这个点,看看还能不能回到前一个点    

        这时候我们就可以再定义一个数组low,这个数组用来记录每个顶点在不经过前一个遍历的顶点时,能够回到的最近(就是截止到此顶点最后被遍历)的结点

        如果存在一个顶点u,图中一个顶点v满足low[v]>=num[u](num是遍历的顺序),那么u就是割点

     

     

    problem set:


    n个城市之间有通讯网络,每个城市都有通讯交换机,直接或间接与其它城市连接。因电子设备容易损坏,需给通讯点配备备用交换机。但备用 交换机数量有限,不能全部配备,只能给部分重要城市配置。于是规定:如果某个城市由于交换机损坏,不仅本城市通讯中断,还造成其它城市通讯中断,则配备备 用交换机。请你根据城市线路情况,计算需配备备用交换机的城市个数,及需配备备用交换机城市的编号。

    很明显这个题是割点:

    但是有一个坑~~

    最开始写的是邻接矩阵,,看看能不能过,想着邻接矩阵能过小数据以后改成邻接表就能过大数据了

    然而最开始还是too young

    别忘了题目描述里并没有说图一定联通

    也就是说我们必须对每一个点都进行遍历,而且不要忘了对根节点的判断。。。

    代码实现如下

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,m,root;
    int num[500000],low[500000],flag[500000],index;//index==++
    int in[500000],stack[500000];
    int sum=0;
    struct edge
    {
        int y,next;
    }e[500000];
    int len=0;
    int link[500000];
    
    void insert(int xx,int yy)
    {
        e[++len].next=link[xx];link[xx]=len;
        e[len].y=yy;    
    }
    
    int top;
    void dfs(int cur)
    {
        int v;
        num[cur]=low[cur]=++index;
        stack[++top]=cur;
        in[cur]=1;
        int temp=0;
        for(int i=link[cur];i;i=e[i].next)
        {
            v=e[i].y;
            if(!num[v])
            {
                dfs(v);
                temp++;
                low[cur]=min(low[cur],low[v]);
                //if(low[v]>=num[cur]&&cur!=1)
                  //  flag[cur]++;
                if((cur==root && temp>1)||(cur!=root && low[v]>=num[cur]))
                    if(!flag[cur]) flag[cur]++,sum++;
            }
            else if(in[v])
            low[cur]=min(low[cur],num[v]);
        }
        if(low[cur]==num[v])
        {
            while(cur!=v)
            {
                v=stack[top--];
                in[v]=0;
            }
        }
    }
    
    int main()
    {
        //freopen("a.in","r",stdin);
        //freopen("a.out","w",stdout);
        int x,y;
        cin>>n;
        while(cin>>x>>y)
        {
            insert(x,y);
            insert(y,x);
        }
        for(int i=1;i<=n;i++)
        {
            if(!num[i])
            {
                root=i;
                dfs(i);
            }
        }
        
        cout<<sum<<endl;
        for(int i=1;i<=n;i++)
        {
            if(flag[i])
                cout<<i<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Java类变量和成员变量初始化过程
    Linux命令学习笔记
    gitlab本地部署方法(ubuntu16.04+gitlab9.5.5)
    Hanoi塔
    求递归算法时间复杂度:递归树
    最大堆/最小堆
    Matlab中plot基本用法
    这是一篇叼炸天的博客
    c++ static理解
    经典排序算法+文件操作~c语言实现
  • 原文地址:https://www.cnblogs.com/supersumax/p/5996298.html
Copyright © 2011-2022 走看看