二,危险系数

题目描述

问题描述
抗日战争时期,冀中平原的地道战曾发挥重要作用。
地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。
我们来定义一个危险系数DF(x,y):
对于两个站点x和y (x != y), 如果能找到一个站点z,当z被敌人破坏后,x和y不连通,那么我们称z为关于x,y的关键点。相应的,对于任意一对站点x和y,危险系数DF(x,y)就表示为这两点之间的关键点个数。
本题的任务是:已知网络结构,求两站点之间的危险系数。

输入

输入数据第一行包含2个整数n(2 < = n < = 1000), m(0 < = m < = 2000),分别代表站点数,通道数;
接下来m行,每行两个整数 u,v (1 < = u, v < = n; u != v)代表一条通道;
最后1行,两个数u,v,代表询问两点之间的危险系数DF(u, v)。

输出

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

样例输入

  1. 7 6
  2. 1 3
  3. 2 3
  4. 3 4
  5. 3 5
  6. 4 5
  7. 5 6
  8. 1 6

样例输出

  1. 2

思路分析

dfs搜图问题

询问通道是否连通,也就是能走到就true,不能走到就false

关键点,也就是起点到终点无论怎么走也必须经过的点,转换一下,

假如起点到终点有t条路径,也就是说必定经过关键点t次(除起点和终点)

也就是说从起点到终点,经过t次的点就是我们要找的点(除起点和终点)

代码实现

  1. package DayT2;
  2. import java.util.Scanner;
  3. public class Main {
  4. // 记录顶点个数
  5. public int n;
  6. // 记录通道连通情况
  7. public int[][] arr = null;
  8. // 记录终点
  9. public int endQ = -1;
  10. // 记录能否到终点
  11. public Boolean flag = false;
  12. // 记录从起点到终点不同路径下每个点经过的次数(不算起点)
  13. public int[] dot = null;
  14. // dfs的vic
  15. public int[] vic = null;
  16. public static void main(String[] args) {
  17. Scanner sca = new Scanner(System.in);
  18. Main main = new Main();
  19. //接收顶点数和边数
  20. main.n = sca.nextInt();
  21. int m = sca.nextInt();
  22. main.init();
  23. //由于是无向图,所以构建邻接矩阵
  24. for (int i = 0; i < m; i++) {
  25. int start = sca.nextInt();
  26. int end = sca.nextInt();
  27. // 站点x和y连通,也就是说能从x到y,也能从y到x
  28. main.arr[start][end] = main.arr[end][start] = 1;
  29. }
  30. //接收起点,终点
  31. int startQ = sca.nextInt();
  32. main.endQ = sca.nextInt();
  33. //dfs
  34. int result = main.dfs(startQ, 0, new int[main.n + 1]);
  35. int count = 0;
  36. //如果两个点不连通,输出-1
  37. if(main.flag==false) {
  38. System.out.println(-1);
  39. }
  40. //记录有多少个点是去终点的必经之点
  41. for (int i = 1; i < main.n + 1; i++) {
  42. if (main.dot[i] == result) {
  43. count++;
  44. }
  45. }
  46. // 减去终点
  47. System.out.println(count - 1);
  48. }
  49. private void init() {
  50. // TODO Auto-generated method stub
  51. arr = new int[n + 1][n + 1];
  52. dot = new int[n + 1];
  53. vic = new int[n + 1];
  54. }
  55. /**
  56. *
  57. * @param startQ:到达的点
  58. * @param step:第几个经过点,0代表起点
  59. * @param temp:从起点到终点经过的点的数组
  60. * @return
  61. */
  62. private int dfs(int startQ, int step, int[] temp) {
  63. // TODO Auto-generated method stub
  64. //如果到达的点为终点,说明已经到了终点,有一条路径了
  65. if (startQ == endQ) {
  66. //将从起点到终点经过点的次数加一
  67. for (int i = 0; i < step; i++) {
  68. dot[temp[i]]++;
  69. }
  70. flag = true;
  71. return 1;
  72. }
  73. int result = 0;
  74. //遍历该点能到的点
  75. for (int i = 1; i < n + 1; i++) {
  76. //如果访问过,continue
  77. if (vic[i] == 1) {
  78. continue;
  79. }
  80. //如果不连通,continue
  81. if (arr[startQ][i] == 0) {
  82. continue;
  83. }
  84. //记录经过的点
  85. temp[step] = i;
  86. //dfs
  87. vic[i] = 1;
  88. result += dfs(i, step + 1, temp);
  89. vic[i] = 0;
  90. }
  91. //返回从startQ到终点路径条数
  92. return result;
  93. }
  94. }
点赞(0)
 

9.9 分

3 人评分

 

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 2 条评论

lizuwangCode 1年前 回复TA
思路很棒!
CONTINUE 3年前 回复TA
一语惊醒梦中人