标题:风险度量
X星系的的防卫体系包含 n 个空间站。这 n 个空间站间有 m 条通信链路,构成通信网。
两个空间站间可能直接通信,也可能通过其它空间站中转。
对于两个站点x和y (x != y), 如果能找到一个站点z,使得:
当z被破坏后,x和y不连通,则称z为关于x,y的关键站点。
显然,对于给定的两个站点,关于它们的关键点的个数越多,通信风险越大。
你的任务是:已经网络结构,求两站点之间的通信风险度,即:它们之间的关键点的个数。
输入数据第一行包含2个整数n(2 <= n <= 1000), m(0 <= m <= 2000),分别代表站点数,链路数。
空间站的编号从1到n。通信链路用其两端的站点编号表示。
接下来m行,每行两个整数 u,v (1 <= u, v <= n; u != v)代表一条链路。
最后1行,两个数u,v,代表被询问通信风险度的两个站点。
输出:一个整数,如果询问的两点不连通则输出-1.
例如:
用户输入:
7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6
则程序应该输出:
2
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
java选手注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
java选手注意:主类的名字必须是:Main,否则按无效代码处理。
c/c++选手注意: main函数需要返回0
c/c++选手注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
c/c++选手注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交程序时,注意选择所期望的语言类型和编译器类型。
思路:
第一想到的是,这道题是求,无向图的两点间最短距离。
第一种解决方式:
使用dfs暴力测试的方式去求该点到最后点的最短路径。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Test {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
//n个顶点 m条连通数据
int n = input.nextInt();
int m = input.nextInt();
//使用map存储图的结构
// Map : key(顶点) value(该顶点可以到达的顶点)
Map<Integer,List<Integer>> map = new HashMap<Integer,List<Integer>>();
for(int i=0;i<m;i++){
int left = input.nextInt();
int right = input.nextInt();
if(!map.containsKey(left)){
map.put(left, new ArrayList<Integer>());
}
if(!map.containsKey(right)){
map.put(right, new ArrayList<Integer>());
}
//A可以连通B
//B也可以连通A
map.get(left).add(right);
map.get(right).add(left);
}
//开始的点
int begin = input.nextInt();
//结束的点
int end = input.nextInt();
//使用set集合防止回路
HashSet<Integer> set = new HashSet<Integer>();
int min = dfs(map,begin,end,set);
System.out.println(min-1);
}
//begin 开始的点 end 结束的点 set防止回路
public static int dfs(Map<Integer,List<Integer>> map,int begin,int end,Set<Integer> set){
//找到结束位置
if ( begin==end )return 0;
//出现顶点冲突,返回无效值,该试探结束
if(set.contains(begin))return Integer.MAX_VALUE-100;
//代表我已经踏上了这个顶点,不可以再次踏上
set.add(begin);
//min 测试该顶点走向最后,那条路最短,
int min = Integer.MAX_VALUE-100;
//得到所有的一级子顶点
List<Integer> list = map.get(begin);
for(int i=0;i<list.size();i++){
//如果该节不是向回走,就进行dfs
if(!set.contains(list.get(i))){
//得到走该顶点的路径
int res = dfs(map,list.get(i),end,set);
//判断得到最短的路径
min = Math.min(min,res+1);
}
}
//已经测试完,该顶点可以到达的所有顶点,回溯下,撤销该定点的不可回路状态
set.remove(begin);
return min;
}
}
然而测试用例大部分都过不了。
5 4
1 3
2 3
1 4
4 5
2 5
3
182 190
37 23
37 146
146 111
111 107
37 87
146 176
37 74
176 77
74 90
74 125
37 63
63 57
77 93
57 152
77 65
74 84
74 149
23 64
125 119
90 72
37 109
149 100
119 91
90 144
91 86
64 78
149 127
65 22
127 31
86 130
149 33
109 96
78 4
125 113
130 62
90 13
62 30
74 118
127 124
84 5
86 131
90 155
74 7
87 9
64 70
62 35
23 11
96 167
9 180
33 83
70 29
146 182
107 139
86 150
96 147
33 47
144 171
29 40
155 153
150 79
83 26
100 173
72 133
84 10
23 68
86 24
146 36
10 103
182 122
63 137
182 108
93 110
146 56
180 145
182 132
7 3
180 19
133 38
93 143
70 120
13 163
107 88
118 75
31 76
56 28
36 32
7 12
72 115
133 45
40 53
64 174
74 105
37 141
171 106
118 17
32 43
103 151
119 27
87 136
65 39
139 46
152 134
147 161
53 48
144 80
62 129
108 172
27 101
45 177
38 162
96 178
143 81
81 67
33 157
153 128
106 69
28 15
110 14
28 50
167 123
83 97
14 20
62 140
105 6
4 1
172 16
38 168
182 60
33 82
68 170
128 2
128 94
105 52
50 154
124 156
56 71
153 98
23 41
5 18
62 116
173 142
60 92
105 55
136 54
23 99
133 102
2 179
133 175
139 85
47 117
86 135
35 112
110 121
152 42
42 34
47 104
110 138
121 49
36 126
136 21
92 158
63 159
178 166
178 164
63 181
119 51
142 66
175 165
178 44
149 58
159 89
165 160
166 148
153 95
106 61
168 73
130 169
45 173
134 176
145 110
91 134
34 83
45 24
119 12
27 133
161 82
176 159
182 85
73 134
3 144
179 36
6
105 106
37 23
23 90
37 42
90 103
23 15
37 82
15 30
42 61
90 45
15 70
61 36
103 56
30 50
103 72
82 8
103 12
15 22
12 26
30 83
82 43
61 3
50 18
18 89
8 52
45 64
64 38
37 57
72 9
15 35
70 46
9 13
57 95
35 105
35 101
23 104
64 69
82 87
8 2
83 54
42 62
15 85
85 94
26 60
89 33
69 49
94 55
62 88
43 51
70 102
12 20
51 28
9 10
56 86
49 91
26 77
89 63
103 93
52 7
26 71
88 19
42 41
82 34
41 1
85 92
55 79
93 73
103 96
71 29
35 47
69 14
20 5
29 74
41 58
58 32
47 100
83 78
37 21
105 6
82 81
96 65
71 67
12 75
6 17
103 97
46 16
79 53
52 76
93 84
89 31
84 98
19 59
54 11
64 24
32 44
63 66
46 4
64 68
15 27
72 99
30 25
4 91
48 52
50 101
47 30
47 102
23 89
67 59
11
再次读题。发现这道题并不是求最短路径的。
题目是当破坏某个点后 A 和 B 不连通 ,这个点才是关键点。
如果是这种结构的话, A:3 B:2 他的关键路径肯定是 4 1 3
换一种结构
关键点就是,只要少了他,A和B 就不能连通了。
重新编程。暴力测试,测试每一个点是不是关键点。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Test {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
//n个顶点 m条连通数据
int n = input.nextInt();
int m = input.nextInt();
//map 结构在遍历的时候添加和删除元素不方便
//换结构
// Map<Integer,List<Integer>> map = new HashMap<Integer,List<Integer>>();
//数组,下标代表各个节点。
List[] map = new List[n+1];
for(int i=0;i<n+1;i++){
map[i] = new ArrayList();
}
for(int i=0;i<m;i++){
int left = input.nextInt();
int right = input.nextInt();
//A可以连通B
//B也可以连通A
map[left].add(right);
map[right].add(left);
}
//开始的点
int begin = input.nextInt();
//结束的点
int end = input.nextInt();
//关键点个数
int count = 0;
//测试除了开始点和结束点,中某一点是不是关键点
for(int i=1;i<n+1;i++){
List<Integer> list = map[i];
//如果为空说明该点没有直接子节点
if(list.isEmpty()||list.size()==0||i==begin||i==end)continue;
//添加一个空的list 代表该 点已经删除 已经走不通了
map[i] = new ArrayList();
//使用set集合防止回路
HashSet<Integer> set = new HashSet<Integer>();
boolean pan = dfs(map,begin,end,set);
if(!pan)count++;
//测试完毕,将这个点填会原来的数据
map[i] = list;
}
System.out.println(count);
}
//看看是否连通
public static boolean dfs(List[] map,int begin,int end,Set<Integer> set){
if(begin==end)return true;
set.add(begin);
List<Integer> list = map[begin];
//这个点已经被删除了,所有直接子节点为空
if(list.isEmpty()||list.size()==0)return false;
for(int i=0;i<list.size();i++){
//没有向回走
if(!set.contains(list.get(i))){
//如果走到了终点就说明连通了
if(dfs(map,list.get(i),end,set)){
return true;
}
}
}
//回溯
set.remove(begin);
return false;
}
}