POJ 1144
来源:互联网 发布:券商资管新规 知乎 编辑:程序博客网 时间:2024/05/21 08:02
题目的意思是要你求出给定的图中有几个关节点。
何为关节点? 简单来说就是在一个完整的图中,如果失去某个结点,这个图将不会完整,会分成几个小图。
我的思路是这样的: 假设这个点是关结点,那么它被删除之后,图的个数肯定会增加,该图至少变成两个图,也就是说存在两个结点的前驱不存在。
我们可以先把图进行深度优先遍历或广度优先遍历,这样我们会得到一组数据存入一个数组中。给结点定义一个结构体,设有前驱和后继并指明该结点的前驱跟后继分别是什么。当然根结点是没有前驱的。 我们可以根据遍历得到的数据顺序依次删除,在删除该结点之后,修改该结点对应的前驱和后继的结点的后继和前驱。然后对图中的前驱为空的结点个数进行判断,若大于1该结点为关结点。 依次类推,每个结点进行判断一次。但是我没有写出对应的代码,下面的代码是用了网友的, 注释是我加的 ,可能有些不对,希望各位指正。
一个结点是否为关节点有两种特征:若他是根结点,则它的子树肯定是大于等于2的。若他是非叶子节点,则它所对应的子树必须通过它才能联系到根。
------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
#define max 100
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
int n, ans;
int map[max][max]; //用来存储输入的顶点
bool isvisted[max]; //用来记录哪些顶点已经访问过了
int gpoint[max];//用来存储判断完不是根结点的结点
int index, root;//被搜索的次数,根结点
int DFN[max], low[max];//表示深度优先搜索某结点,表示某结点子树中的最小序号
void tarjan(int u)
{
DFN[u] = low[u] = ++index;
isvisted[u] = true;//设定该结点已经被访问过
int i;
for ( i = 1; i <=n; ++i)
{
if (map[u][i])
{
if (!isvisted[i])//该边有条顶点没有被访问过,继续根据该顶点搜索下去
{
tarjan(i);
low[u] = Min(low[u], low[i]);//更新当前子树中的最小序号
if (low[i]>=DFN[u] && u!=1)//表示只有通过u才能访问u的祖先 一定要有等于号 不然会丢失结点为树根的情况
{
gpoint[u]++;
}
else if (u==1)//表示该结点是根结点
{
root++;
}
}
else//表示已经访问过该节点
{
low[u] = Min(low[u], DFN[i]);
}
}
}
}
int main()
{
while (scanf("%d",&n)&&n)//确定有几个节点数
{
int u, v;
memset(map,0,sizeof(map));
memset(isvisted, false, sizeof(isvisted));
memset(gpoint, 0, sizeof(gpoint));
ans = root = index = 0;
while (scanf("%d",&u)&&u)//u代表某一具体的结点
{
while (getchar()!='\n')
{
scanf("%d", &v);//与u对应的边的另一结点
map[u][v] = 1;
map[v][u] = 1;
}
}
tarjan(1);
if (root>1)
{
ans++;
}
for (int i = 2; i <=n; ++i)//前面已经判断过根结点是否为关节点,只要从搜索顺序的第二结点进行判断即可
{
if (gpoint[i])
{
ans++;
}
}
printf("%d\n", ans);
}
system("pause");
return 0;
#include<stdlib.h>
#include<string.h>
using namespace std;
#define max 100
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
int n, ans;
int map[max][max]; //用来存储输入的顶点
bool isvisted[max]; //用来记录哪些顶点已经访问过了
int gpoint[max];//用来存储判断完不是根结点的结点
int index, root;//被搜索的次数,根结点
int DFN[max], low[max];//表示深度优先搜索某结点,表示某结点子树中的最小序号
void tarjan(int u)
{
DFN[u] = low[u] = ++index;
isvisted[u] = true;//设定该结点已经被访问过
int i;
for ( i = 1; i <=n; ++i)
{
if (map[u][i])
{
if (!isvisted[i])//该边有条顶点没有被访问过,继续根据该顶点搜索下去
{
tarjan(i);
low[u] = Min(low[u], low[i]);//更新当前子树中的最小序号
if (low[i]>=DFN[u] && u!=1)//表示只有通过u才能访问u的祖先 一定要有等于号 不然会丢失结点为树根的情况
{
gpoint[u]++;
}
else if (u==1)//表示该结点是根结点
{
root++;
}
}
else//表示已经访问过该节点
{
low[u] = Min(low[u], DFN[i]);
}
}
}
}
int main()
{
while (scanf("%d",&n)&&n)//确定有几个节点数
{
int u, v;
memset(map,0,sizeof(map));
memset(isvisted, false, sizeof(isvisted));
memset(gpoint, 0, sizeof(gpoint));
ans = root = index = 0;
while (scanf("%d",&u)&&u)//u代表某一具体的结点
{
while (getchar()!='\n')
{
scanf("%d", &v);//与u对应的边的另一结点
map[u][v] = 1;
map[v][u] = 1;
}
}
tarjan(1);
if (root>1)
{
ans++;
}
for (int i = 2; i <=n; ++i)//前面已经判断过根结点是否为关节点,只要从搜索顺序的第二结点进行判断即可
{
if (gpoint[i])
{
ans++;
}
}
printf("%d\n", ans);
}
system("pause");
return 0;
}
0 0
- poj 1144
- poj 1144
- Poj 1144
- POJ 1144
- poj 1144
- POJ 1144
- poj 1144
- POJ 1144
- POJ 1144 Network
- tarjan求割点 poj 1144
- poj 1144(求割点)
- POJ 1144 求割点
- POJ 1144 Network
- POJ-1144-Network
- POJ 1144 Network
- POJ 1144 Network
- poj 1144 Network 关节点
- Poj 1144 Network
- windows下的xshell远程连接局域网…
- 记录Linux下安装elasticSearch时遇…
- WebService的讨论
- FIR数字滤波器设计频率抽样法MATLAB仿真
- 数据结构--静态链表
- POJ 1144
- Linux基本教程————Linux软件安装之Yum,源码编译安装
- 怎样改变Myeclipse中控制台的字体大小
- ExecutorService中submit和execute的区别
- 基于OpenCV的条形码区域检测(五)
- 【编程知识】面向对象基础知识总结
- C语言习题——编写一个程序,生产一个乘法表
- 排序算法(七)海量数据的排序问题
- 阿里云的CentOS环境中安装配置MySQL的教程