关闭

hiho一下 第五十二周(割边 割点)

238人阅读 评论(0) 收藏 举报
分类:

最近做到了割边割点的东西。就把这几天学到的写下来。

在一个无向图中。

割点:就是删除了这个点,图会不在连通或者连通分量增加。

割边:删除一条边,图会不在连通或者连通分量增加。


做割点时候,会用到两个数组。low[],dfn[]、

low[]数组保存的可以回到祖先的最小节点。
dfn[]数组保存的是当前节点的序列号,可能和题目给出的序列号不是一个数字,要看走的顺序。


然后又由于删除一个点后,当这个点是割点之后,那么这个点的子节点就不会返回到之前的祖先。


当U指向V

low[now]=min(low[now],dfn[v]);当遇到返祖边的时候

low[now]=min(low[now],low[v]);


割点的判断if(child>1&&now==1||now!=1&&low[v]>=dfn[now])

当他的low[]的子节点大于等于他的话。则说明这个点是他的祖先。

假如这个点不是起点的话, 一定是这个图的割点。将这个分割开的点。

假如是起点话,需要两个以上的子树。


以hiho一下 第五十二周 的题目为例。点击打开链接

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1000001;
const int INF=1<<29;
int n,m,sum;
int e,cnt[maxn],kk=0;;
int head[maxn],nxt[maxn],pnt[maxn];
int low[maxn],dfn[maxn],vis[maxn];
//low[]数组保存的可以回到祖先的最小节点。
//dfn[]数组保存的是当前节点的序列号,可能和题目给出的序列号不是一个数字,要看走的顺序。
int aa[maxn],ck=0;
struct node
{
    int x,y;
}num[maxn];
int cmp(node p1,node p2)
{
    if(p1.x==p2.x) return p1.y<p2.y;
    return p1.x<p2.x;
}
void AddEdge(int u,int v)
{
    pnt[e]=v;nxt[e]=head[u];head[u]=e++;
}

void dfs(int now,int father,int dfnth)
{
    low[now]=dfn[now]=dfnth;
    vis[now]=1;
    int child=0;
    //printf("==%d %d %d\n",now,father,dfnth);
    for(int i=head[now];i!=-1;i=nxt[i])
    {
        if(pnt[i]!=father&&vis[pnt[i]]==1){//遇到返祖边的时候,就更新low[]值
               // printf("!!%d %d %d %d\n",now,pnt[i],father,dfn[pnt[i]]);

            low[now]=min(low[now],dfn[pnt[i]]);
        }
        if(!vis[pnt[i]])
        {
            dfs(pnt[i],now,dfnth+1);
            child++;
            low[now]=min(low[now],low[pnt[i]]);
            if(low[pnt[i]]>dfn[now])//割边
            {
                num[kk].x=min(now,pnt[i]);
                num[kk++].y=max(now,pnt[i]);

            }
             if(child>1&&now==1||now!=1&&low[pnt[i]]>=dfn[now])//割点,
            {
                cnt[now]=1;
                sum++;
            }
        }
    }

    vis[now]=2;
}
int main()
{
    scanf("%d%d",&n,&m);
    e=0;
    sum=0;
    memset(head,-1,sizeof(head));
    memset(dfn,0,sizeof(dfn));
    memset(vis,0,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    int u,v;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        AddEdge(u,v);
        AddEdge(v,u);
    }
    if(n==2)
    {
        puts("NULL");
        puts("1 2");
        return 0;
    }
    dfs(1,-1,1);
    for(int i=1;i<=n;i++)
        printf("%d ",low[i]);puts("");
    for(int i=1;i<=n;i++)
        printf("%d ",dfn[i]);puts("");
    if(sum!=0)
    {
        for(int i=1; i<=n; i++)
            if(cnt[i])aa[ck++]=i;
        for(int i=0; i<ck; i++)
            printf("%d%c",aa[i],i==ck-1?'\n':' ');
    }
    else
        puts("Null");
    if(kk!=0)
    {
        sort(num,num+kk,cmp);
        printf("%d %d\n",num[0].x,num[0].y);
        for(int i=1; i<kk; i++)
            if(num[i-1].x!=num[i].x||num[i-1].y!=num[i].y)
                printf("%d %d\n",num[i].x,num[i].y);
    }

    return 0;
}
/*
6 7
1 2
2 3
3 1
2 4
4 5
5 6
6 4

8 12
1 2
2 3
2 1
2 4
3 2
3 4
4 2
4 3
4 5
5 4
8 7
7 8

6 8
2 5
1 2
2 3
3 1
3 4
4 5
5 6
6 4

7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7
*/



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:42808次
    • 积分:1259
    • 等级:
    • 排名:千里之外
    • 原创:85篇
    • 转载:9篇
    • 译文:0篇
    • 评论:3条