SPF Tarjan算法求无向图割点(关节点)入门题

                                    SPF

题目抽象,给出一个连通图的一些边,求关节点。以及每个关节点分出的连通分量的个数

邻接矩阵只要16ms,而邻接表却要32ms,  花费了大量的时间在加边上。

//   time  16ms

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <string>
  7 #include <vector>
  8 #include <set>
  9 #include <map>
 10 #include <stack>
 11 #include <queue>
 12 #include <sstream>
 13 #include <iomanip>
 14 using namespace std;
 15 typedef long long LL;
 16 const int INF = 0x4fffffff;
 17 const double EXP = 1e-5;
 18 const int MS = 1005;
 19 const int SIZE = 100005;
 20
 21 int edges[MS][MS];
 22 int vis[MS];
 23 int dfn[MS];
 24 int low[MS];
 25 int subnets[MS];
 26 int nodes;
 27 int tdfn;
 28 int sons;
 29
 30 void init()
 31 {
 32       low[1]=dfn[1]=1;
 33       tdfn=1;sons=0;nodes=0;
 34       memset(vis,0,sizeof(vis));
 35       vis[1]=1;
 36       memset(subnets,0,sizeof(subnets));
 37       memset(edges,0,sizeof(edges));
 38 }
 39
 40 void DFS(int u)
 41 {
 42       for(int v=1;v<=nodes;v++)
 43       {
 44             if(edges[u][v])
 45             {
 46                   if(!vis[v])
 47                   {
 48                         vis[v]=1;
 49                         dfn[v]=low[v]=++tdfn;       //  初始化
 50                         DFS(v);                                //   low[v]的值已经求出
 51                         low[u]=min(low[u],low[v]);
 52                         if(low[v]>=dfn[u])
 53                         {
 54                               if(u!=1)
 55                                     subnets[u]++;
 56                               else
 57                                     sons++;
 58                         }
 59                   }
 60                   else                   //  v已经访问过了,v是u的祖先节点,(v,u)是一条回边
 61                         low[u]=min(low[u],dfn[v]);
 62             }
 63       }
 64 }
 65
 66 int main()
 67 {
 68       int u,v,find,number=1;
 69       while(1)
 70       {
 71             scanf("%d",&u);
 72             if(!u)
 73                   break;
 74             init();
 75             scanf("%d",&v);
 76             if(u>nodes)
 77                   nodes=u;
 78             if(v>nodes)
 79                   nodes=v;
 80             edges[u][v]=edges[v][u]=1;
 81             while(1)
 82             {
 83                   scanf("%d",&u);
 84                   if(!u)
 85                         break;
 86                   scanf("%d",&v);
 87                   if(u>nodes)
 88                         nodes=u;
 89                   if(v>nodes)
 90                         nodes=v;
 91                   edges[u][v]=edges[v][u]=1;
 92             }
 93             if(number>1)
 94                   printf("\n");
 95             printf("Network #%d\n",number++);
 96             DFS(1);
 97             if(sons>1)
 98                   subnets[1]=sons-1;
 99             find=0;
100             for(int i=1;i<=nodes;i++)
101             {
102                   if(subnets[i])
103                   {
104                         find=1;
105                         printf("  SPF node %d leaves %d subnets\n",i,subnets[i]+1);
106                   }
107             }
108             if(!find)
109                   printf("  No SPF nodes\n");
110
111       }
112       return 0;
113 }

邻接表    time==32ms

  1 // time 32ms
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <string>
  8 #include <vector>
  9 #include <set>
 10 #include <map>
 11 #include <stack>
 12 #include <queue>
 13 #include <sstream>
 14 #include <iomanip>
 15 using namespace std;
 16 typedef long long LL;
 17 const int INF = 0x4fffffff;
 18 const double EXP = 1e-5;
 19 const int MS = 1005;
 20 const int SIZE = 100005;
 21
 22 //int edges[MS][MS];
 23 struct edge
 24 {
 25       int v,next;
 26 }edges[(MS*MS)];      //  理论上是(MS*MS)<<1,超内存。但这种情况是超级极端。(MS*MS)足够
 27 int head[MS];
 28
 29 int vis[MS];
 30 int dfn[MS];
 31 int low[MS];
 32 int subnets[MS];
 33 int nodes;
 34 int tdfn;
 35 int sons;
 36 int cnt;
 37
 38 void init()
 39 {
 40       low[1]=dfn[1]=1;
 41       tdfn=1;sons=0;
 42       nodes=0;cnt=0;
 43       memset(vis,0,sizeof(vis));
 44       vis[1]=1;
 45       memset(subnets,0,sizeof(subnets));
 46       memset(edges,0,sizeof(edges));
 47       memset(head,-1,sizeof(head));
 48 }
 49
 50 void add(int u,int v)
 51 {
 52       edges[cnt].v=v;edges[cnt].next=head[u];head[u]=cnt++;
 53       edges[cnt].v=u;edges[cnt].next=head[v];head[v]=cnt++;
 54 }
 55
 56 void DFS(int u)
 57 {
 58       for(int i=head[u];i!=-1;i=edges[i].next)
 59       {
 60             int v=edges[i].v;
 61             if(!vis[v])
 62             {
 63                   vis[v]=1;
 64                   dfn[v]=low[v]=++tdfn;
 65                   DFS(v);
 66                   low[u]=min(low[u],low[v]);
 67                   if(low[v]>=dfn[u])
 68                   {
 69                         if(u!=1)
 70                               subnets[u]++;
 71                         else
 72                               sons++;
 73                   }
 74             }
 75             else
 76                   low[u]=min(low[u],dfn[v]);
 77       }
 78 }
 79
 80 int main()
 81 {
 82       int u,v,find,number=1;
 83       while(1)
 84       {
 85             scanf("%d",&u);
 86             if(!u)
 87                   break;
 88             init();
 89             scanf("%d",&v);
 90             if(u>nodes)
 91                   nodes=u;
 92             if(v>nodes)
 93                   nodes=v;
 94            add(u,v);
 95             while(1)
 96             {
 97                   scanf("%d",&u);
 98                   if(!u)
 99                         break;
100                   scanf("%d",&v);
101                   if(u>nodes)
102                         nodes=u;
103                   if(v>nodes)
104                         nodes=v;
105                 add(u,v);
106             }
107             if(number>1)
108                   printf("\n");
109             printf("Network #%d\n",number++);
110             DFS(1);
111             if(sons>1)
112                   subnets[1]=sons-1;
113             find=0;
114             for(int i=1;i<=nodes;i++)
115             {
116                   if(subnets[i])
117                   {
118                         find=1;
119                         printf("  SPF node %d leaves %d subnets\n",i,subnets[i]+1);
120                   }
121             }
122             if(!find)
123                   printf("  No SPF nodes\n");
124       }
125       return 0;
126 }
时间: 2024-10-09 08:20:55

SPF Tarjan算法求无向图割点(关节点)入门题的相关文章

tarjan算法--求无向图的割点和桥

一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中,如果删除某点后,图变成不连通,则称该点为割点. 二:tarjan算法在求桥和割点中的应用 1.割点:1)当前节点为树根的时候,条件是“要有多余一棵子树”(如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了.) 2)当前节点U不是树根的时候,条件是“low[v]>=

Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释

 原题链接   无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍, 看其low和dfn,满足dfn[ fa ]<low[ i ](0<i<=n, i 的 father为fa) -- 则桥为fa-i. 找桥的时候,要注意看有没有重边:有重边,则不是桥. 另外,本题的题意及测试样例中没有重边,所以不用考虑重边. 带详细注释的题解: #include<s

Tarjan 算法求无向图的割顶和桥

#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int N = 250; int head[N], low[N], dfn[N], fa[N]; int n, m, now = 1, Tarjan_clock; bool is_cut[N]; struct Node{ int u, v, nxt; }E[N]; inline int read()

Tarjan求无向图割点、桥详解

tarjan算法--求无向图的割点和桥 一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中,如果删除某点后,图变成不连通,则称该点为割点. 二:tarjan算法在求桥和割点中的应用 1.割点:1)当前节点为树根的时候,条件是"要有多余一棵子树"(如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了.) 2)

tarjan算法求关节点

求无向图的关节点 dfn[]来存点的深度数 在一张深度优先搜索树中,如果u和v是两个顶点,且生成树中u是v的祖先,则必有dfn[u]<dfn[v],表明u先被访问. 回边:原图中除了dfs树中的边外,还有的边叫回边:如:1->2,1->3,2->3中,dfs时1->2->3,这里dfs树中的边为1->2,2->3,那么1->3就是回边: (1)如果点u是dfs生成树的根,那么u至少有2个子女.理由:因为一删除u,它的子女所在的子树就断开了. (2)如果

ZOJ Problem - 2588 Burning Bridges tarjan算法求割边

题意:求无向图的割边. 思路:tarjan算法求割边,访问到一个点,如果这个点的low值比它的dfn值大,它就是割边,直接ans++(之所以可以直接ans++,是因为他与割点不同,每条边只访问了一遍). 需要注意的就是此处有多重边,题目中要求输出确定的不能被删除的边,而多重边的保留不是可以确定的,所以多重边都是不可以被保留的,我们可以在邻接表做一个flag的标记,判断他是不是多重边. 注意建图的时候数组应该是m × 2,因为这里是无向边,当心RE! 注意输出的时候编号是必须要拍好序再输出. 还有

HDU 1269 迷宫城堡 tarjan算法求强连通分量

基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等,那这个点就在一个强连通分量里面,此时从栈中向外取出元素,知道取出的元素与这个点的值相等时结束,我们所有取出的点与这个点在同一个强连通分量里.下面是代码,其实代码里本来不需要id数组记录点属于哪个强连通分量的,因为题目没有做要求,但是为了保留模板完整还是带着了,以供以后复习使用. #include<c

图论算法(6)(更新版) --- Tarjan算法求强连通分量

之前Tarjan算法求强连通分量博文中,代码实现用到了固定大小数组,扩展起来似乎并不是很方便,在java里这样来实现本身就是不太妥当的,所以下面给出一个更新版本的代码实现: package test; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util

tarkjan求无向图割点模板

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 int n,m; 6 const int maxn=1e5+2; 7 const int maxm=maxn<<1; 8 struct node 9 { 10 int to; 11 int nxt; 12 }e[maxm]; 13 int head[maxn]; 14 int tot; 15 int id; 16 int root