ACM坑中人. 蒟蒻爬虫

supersumax

noip的坑中人

图的割点 | | 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;
}

 

posted on 2016-10-25 12:56  supersumax  阅读(237)  评论(0编辑  收藏  举报

导航