问题描述
抗日战争时期,冀中平原的地道战曾发挥重要作用。
地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。
我们来定义一个危险系数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.
样例输入
7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6
样例输出
2
import java.util.LinkedList;
import java.util.Scanner;
public class 危险系数 {
/**
* @param args
*/
static int end;
static int sum=0;//路径和
//所有可能路径组成的字符串
static LinkedList<String> ll=new LinkedList<String>();
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();//节点数
int m=sc.nextInt();//边数
int map[][]=new int[m+1][m+1];//邻接矩阵
for (int i = 1; i <= m; i++) {
int x1=sc.nextInt();
int y1=sc.nextInt();
map[x1][y1]=1;
}
int t1=sc.nextInt();//询问的节点1 初始节点
int t2=sc.nextInt();//询问的节点2 结束节点
end=t2;
int vis[]=new int[n+1];
LinkedList<Integer> list=new LinkedList<Integer>();
dfs(map,vis,list,t1);
int vs[]=new int[n+1];//记录各个节点出现的次数,如果出现次数与所有可能的路径和值相等
//那么证明这个节点出现在了所有可能路径中,所以这些点就是“关键点”
for (int i = 1; i <= n; i++) {
if(i==t1 || i==t2){//刨去初始和结束节点
continue;
}
for (int k = 0; k < ll.size(); k++) {
if(ll.get(k).contains(String.valueOf(i))){
vs[i]++;
}
}
}
int jus=0;//关键点个数
for (int i = 0; i < vs.length; i++) {
if(vs[i]==sum){//相同记录
jus++;
}
}
if(jus==0){
System.out.println("-1");
}else {
System.out.println(jus);
}
}
/**
* 遍历邻接矩阵,找到所有可能的路径,并转化为字符串
* @param map 邻接矩阵
* @param vis 记忆表
* @param list 记录路径
* @param cur 当前节点
*/
private static void dfs(int[][] map, int[] vis, LinkedList<Integer> list, int cur) {
if(cur==end){
sum++;
String s="";
for (int i = 0; i < list.size(); i++) {
s+=list.get(i);
}
ll.add(s);
return;
}
for (int j = 1; j < map.length; j++) {
if(j==cur){
continue;
}
if(map[cur][j]==1 && vis[j]==0){
list.add(j);
vis[j]=1;
dfs(map,vis,list,j);
list.removeLast();
vis[j]=0;
}
}
}
}