割点割边连通分量等连通性相关算法

7 篇文章 0 订阅
5 篇文章 0 订阅

FloodFill

不说了….大家都会写…..

无向图割点Tarjan算法

主过程是一个DFS.
我们使用DFS对每个点记录两个值:
1.dfn[i] 表示点i是第几个DFS到的点.
2.low[i] 表示从点i出发,不经过DFS的点能绕回而取得的最小的dfn值.
那么当low[i]==dfn[i]时,i的子节点就只能从一条不是DFS中路径的路径回到自己,而不能回到i的父节点.
于是我们就可以断定i是一个割点.
dfn很好理解.
但是low怎么理解呢?
显然,我们的主要目的是找环.
假设我们DFS,经过了点i,到达点j.
那么DFS路径必定是一条点i到点j的路径.
我们想要找环,就一定不能从DFS路径走,而是要从别的地方走.
low一直取min就是为了使找到的环尽量大,使得它是极大环,只有这样的环才是一个严格的连通分量.

Code
#include <cstdio>
#include <iostream>
#include <fstream>

#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cstring>

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;

int getint()
{
    int res=0; char c=getchar(); bool m=false;
    while(c<'0' || c>'9') m=(c=='-'),c=getchar();
    while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
    return m ? -res : res;
}

const db eps=1e-18;
bool feq(db a,db b)
{ return fabs(b-a)<eps; }

using namespace std;

const int INF=(1<<30)-1;

struct edge
{
    int in;
    edge*nxt;
}pool[200000];
edge*et=pool;
edge*eds[1050];
inline edge*addedge(int i,int j)
{ et->in=j; et->nxt=eds[i]; eds[i]=et++; }
#define FOREACH_EDGE(i,j) for(edge*i=eds[j];i;i=i->nxt)

int n,m;
bool used[1050];

int dfn[1050];
int low[1050];
int cnt[1050];
int f[1050];
bool ins[1050];
int cur;
void DFS(int x)
{
    used[x]=true;
    low[x]=dfn[x]=cur++;

    ins[x]=true;

    FOREACH_EDGE(i,x)
    {
        if(!used[i->in])
        {
            DFS(i->in);
            if(low[i->in]==dfn[x]) cnt[x]++;
            low[x]=min(low[x],low[i->in]);
        }else
        {
            if(i->in!=f[x])
            low[x]=min(low[x],dfn[i->in]);
        }
    }

    ins[x]=false;
}

void INIT()
{
    et=pool;
    memset(eds,0,sizeof(eds));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(cnt,0,sizeof(cnt));
    memset(f,0,sizeof(f));
    memset(used,0,sizeof(used));
}

int main()
{
    int a,b,T=1;
    while(a=getint())
    {
        b=getint();
        INIT();
        addedge(a,b);
        addedge(b,a);
        while(a=getint())
        {
            b=getint();
            addedge(a,b);
            addedge(b,a);
        }

        cur=1;
        f[1]=1;
        DFS(1);

        printf("Network #%d\n",T);

        int tot=0;


        if(cnt[1]>=2)
            printf("  SPF node %d leaves %d subnets\n",1,cnt[1]),tot++;

        for(int i=2;i<=1000;i++)
        {
            if(cnt[i]!=0)
            {
                printf("  SPF node %d leaves %d subnets\n",i,cnt[i]+1);
                tot++;
            }
        }

        if(!tot)
            printf("  No SPF nodes\n");

        printf("\n");

        T++;
    }
    return 0;
}

未完待续

无向图割边

有向图割点

有向图割边

强连通分量Tarjan算法

双连通分量Tarhan算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值