NCSTOJ: [啊哈算法]重要城市(图的割点)

Description

一场大战即将开始…

我们已经掌握了敌人的城市地图,为了在战争中先发制人,决定向敌人的某个城市上空投放炸弹,来切断敌人城市之间的通讯和补给,城市地图如下:

我们可以炸毁2号城市,这样剩下的城市之间就不能两两相护到达了。

Input
第一行有两个整数n,m。n表示有n个顶点,m表示有m条边,

接下来m行,每行形如“a b”表示顶点a和顶点b之间有边。

Output
输出要炸毁的城市。

Sample Input
6 7
1 4
1 3
4 2
3 2
2 5
2 6
5 6
Sample Output
2

#include<iostream>
#include<algorithm>
using namespace std;
int e[9][9],n,m,index,root;//e数组用来存储邻接表  index用来记录时间戳  root用来表示根结点
int num[9],flag[9],low[9];//num数组用来记录当前结点的时间戳   flag数组用来记录割点   low数组用来记录能够到达的最小的时间戳
//这里有一个数据关系当一个结点的能够到达的最小的时间戳小于本身的时间戳时说明在搜索的过程中到达过本结点的之前的结点
//即能够构成一个闭环   而且一个闭环阻断一点仍然是能够通过的  所以是能够判断该结点不是割点的
void dfs(int cur,int father)//传入当前结点和父结点
{int child,i,j;//child用来记录该结点的孩子的个数
	index++;//首先时间戳加1
    num[cur]=index;//num数组记录时间戳
    low[cur]=index;//本结点能到达的最小的时间戳初始化为其本身的时间戳

for(i=1;i<=n;i++)//通过对全部结点的遍历寻找与当前结点有关的结点
{
if(e[cur][i]==1)//当前结点与i结点之间有联系
{
if(num[i]==0)//当i结点时间戳为0,即还没访问过时
{

child++;
dfs(i,cur);//进行下一步深度优先搜索
//通过与新的i结点的最小到达时间戳进行比较,来更新本结点的能够到达最小的时间戳

low[cur]=min(low[cur],low[i]);

//当判断割点时还要分根结点情况和非根结点情况

if(cur!=root&&low[i]>=num[cur])//根据开始的数据结构的分析能够不形成闭环
	flag[cur]=1;







}
else if(i!=father)//为了放置无限循环的发生即一直进行向前向后的搜索,这也是深度优先搜索的要求
{
low[cur]=min(low[cur],num[i]);//因为i结点先于cur搜索过了
//该步更新最小时间戳的操作相当与扩大当前结点能够形成的闭环的范围:
//当low[cur]<num[i]时说明本结点能够到达的最小的时间戳比num[i]小即已经形成的闭环比从cur到i形成的闭环要大
//当num[i]<low[cur]时说明本结点还没有形成的闭环或原来的闭环要小于此时新形成的闭环
//

}



}



}




}
int main(){
cin>>n>>m;


for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
		e[i][j]=0;//初始化邻接表




for(int i=1;i<=m;i++)
{
	int x,y;
	cin>>x>>y;//建立新的邻接表
	e[x][y]=1;
	e[y][x]=1;
}
root=1;//建立根结点
dfs(1,root);


for(int i=1;i<=n;i++)
	if(flag[i]==1)cout<<i<<" ";
return 0;











}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值