洛谷 P8604 [蓝桥杯 2013 国 C] 危险系数

题面

题目背景

抗日战争时期,冀中平原的地道战曾发挥重要作用。

题目描述

地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。

我们来定义一个危险系数 $DF(x,y)$

对于两个站点 $x$ 和 $y(x\neq y)$, 如果能找到一个站点 $z$,当 $z$ 被敌人破坏后,$x$$y$ 不连通,那么我们称 $z$ 为关于 $x,y$ 的关键点。相应的,对于任意一对站点 $x$$y$,危险系数 $DF(x,y)$ 就表示为这两点之间的关键点个数。

本题的任务是:已知网络结构,求两站点之间的危险系数。

输入格式

输入数据第一行包含 $2$ 个整数 $n(2 \le n \le 1000)$$m(0 \le m \le 2000)$,分别代表站点数,通道数。

接下来 $m$ 行,每行两个整数 $u,v(1 \le u,v \le n,u\neq v)$ 代表一条通道。

最后 $1$ 行,两个数 $u,v$,代表询问两点之间的危险系数 $DF(u,v)$

输出格式

一个整数,如果询问的两点不连通则输出 $-1$

样例 #1

样例输入 #1

7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6

样例输出 #1

2

提示

时限 1 秒, 64M。蓝桥杯 2013 年第四届国赛

一句话题意

给定一个无向图,求从起点 $u$ 到终点 $v$ 的所有路径上重复的点,若  $u$ 与 $v$ 不联通,则输出 $-1$ 。

解题

思路

我们可以使用深度优先搜索(DFS)来计算两个站点之间的危险系数。

具体步骤如下:

  1. 构建图数据结构。我们可以使用邻接表或邻接矩阵来表示图。邻接表更适合表示稀疏图,而邻接矩阵适合表示稠密图。当然也可以用 $vector$ 动态数组。

  2. 使用DFS遍历图。从任意一个站点开始,对于每个未访问过的相邻站点,递归调用DFS进行遍历。当到达终点时,我们要累加每个点被遍历的个数。

  3. 根据询问的两个站点,查找所有 $ans$ 条路径中有重复 $ans$ 次的点就为关键点,并累计个数输出。

vector 的存图与遍历 

zxy[v].push_back(u);//存图 
zxy[u].push_back(v);

for(int i=0;i<zxy[x].size();i++)
{
	if(i==fa)//i 为 x 的父亲节点 
		continue;
	dfs(i);
}

代码实现

#include<bits/stdc++.h>
#define Z return
#define X 0
#define Y ;
using namespace std;
const int N=1010,M=N*2;
int head[N],Next[M],ver[M],tot;//邻接表 
void add(int x,int y)
{
	ver[++tot]=y;
	Next[tot]=head[x];
	head[x]=tot;
}
int n,m,v[N];
int s,e,ans,d[N];
void dfs(int x)
{
	if(x==e)//到终点 
	{
		ans++;//总路径数 
		for(int i=1;i<=n;i++)//累计每个点被遍历的次数 
			if(v[i]==1)
				d[i]++;
		return ;
	}
	v[x]=1;
	for(int i=head[x];i;i=Next[i])//邻接表的遍历 
	{
		int y=ver[i];
		if(v[y]==1)
			continue;
		dfs(y);
		v[y]=0;//回溯,以遍历下一条路 
	}
}
int main()
{
	scanf("%d%d",&n,&m);//read 
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);//存图 
	}
	scanf("%d%d",&s,&e);
	dfs(s);
	if(ans==0)// u 与 v 不联通 
	{
		puts("-1");
		return 0;
	}
	int sum=0;
	for(int i=1;i<=n;i++)//关键点的个数
		if(d[i]==ans)
			sum++;
	printf("%d",sum-1);//多算了起点,所以减一(坑) 
	Z X Y
}

赞赞赞~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值