您的位置:首页 > 其它

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

2015-02-18 17:45 316 查看

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算法

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: