您的位置:首页 > 其它

作业

2016-07-19 20:45 211 查看

tarjan算法 无向图

割点

如果在连通图G中去掉一个顶点(自然同时去掉与该顶点相关联的所有边)后,该图的连通分支数增加,则称该顶点为G的割点

割边

使连通图G的边e不在G的任何一个圈上

割点集合

在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合

割边集合

如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合

点连通度

最小割点集合中的顶点数

边连通度

最小割边集合中的边数

~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~

割点

tarjan DFS 对DFS树树根进行判断,是否>1,对于其他的点u,如果非树根的直接son,而且low[u]>=dfn[p[u]],则该点的father v=p[u]使割点。

割边

1,无重边情况,遍历发现T边(u,v)并low[v]>=dfn[u],则(u,v)是割边

2,有重边情况,标记,不能用dfn[u]更新low[v];

例题

POJ的= =!次元地狱门(其实很简单)

输入

输入会包括若干网络的描述。一个网络描述会包括若干对的整数,每行一对整数来描述节点的连接情况,先后顺序是无关的,如:1 2和2 1描述了相同的连接。所有的节点编码会从1到1000.一个单独的0行来结束连接节点的列表。一个空的网络描述结束输入。输入文档中空白的行要被忽略。

输出

对于每个输入的网络中,你需要输出存在的SPF节点的列表在文档中。

文档中第一个网络需要用“Network #1”来定义,第二个则是” Network #2”等等(如样例)。每个SPF节点,输出一行,方式如下方例子所示,列出节点的编号和当这个节点失效时完全连通的子网络的个数。如果网络中没有SPF节点,输出“NO SPF nodes“即可。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这题的难点其实并不是无向图系列,而是输入方式= =,其他的只要套模板就能过= =

输入用while(),就像这样:

int t=9999;
while(t!=0){
int i=0;
P++;
for(i=0;i<2;i++){
scanf("%d",&m);
if(m==0){
t=0;
break;
}
if(i==0){
n=m;
}
}
addedge(n,m);


其实可以更简单= =,不过我不说~

完整代码如下

#include<stdio.h>
#include<string.h>
struct node{
int to;
int next;
} p[1005*1005];
int dfn[1005],low[1005];
int vis[1005];
int cut[1005],head[1005];
int n,e,idex;
int root,root_son;
int max(int a,int b){
return a<b?b:a;
}
void add(int u,int v){
p[e].to=v;
p[e].next=head[u];
head[u]=e++;
}
void findCut(int u){
dfn[u]=low[u]=idex++;
for(int i=head[u]; i!=-1; i=p[i].next){
int v=p[i].to;
if(!dfn[v]){
findCut(v);
if(u==root)
root_son++;
else{
if(low[v]<low[u])
low[u]=low[v];
if(low[v]>=dfn[u])
cut[u]=1;
}
}
else if(low[u]>dfn[v])
low[u]=dfn[v];
}
}
void dfs(int s){
vis[s]=1;
for(int i=head[s]; i!=-1; i=p[i].next){
int v=p[i].to;
if(!vis[v]){
vis[v]=1;
dfs(v);
}
}
}
int main(){
int u,v,t=0;
while(scanf("%d",&u)&&u){
t++;
n=-1;
e=0;
idex=1;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(cut,0,sizeof(cut));
memset(head,-1,sizeof(head));
n=max(n,u);
scanf("%d",&v);
n=max(n,v);
add(u,v);
add(v,u);
while(scanf("%d",&u)&&u){
n=max(n,u);
scanf("%d",&v);
n=max(n,v);
add(u,v);
add(v,u);
}
root=1;
int flag=0;
root_son=0;
findCut(root);
if(root_son>1)
cut[root]=1;
printf("Network #%d\n",t);
for(int i=1; i<=n; i++){
if(cut[i]){
flag=1;
memset(vis,0,sizeof(vis));
vis[i]=1;
int son=0;
for(int j=head[i]; j!=-1; j=p[j].next){
if(!vis[p[j].to])
{
dfs(p[j].to);
son++;
}
}
printf("  SPF node %d leaves %d subnets\n",i,son);
}
}
if(!flag)
printf("  No SPF nodes\n");
printf("\n");
}
return 0;
}


坑爹的文本编辑啊,输了好久的都不见了,就剩这破代码了。。哎。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法