蓝桥杯-2017模拟赛本科试题-风险度量

蓝桥杯-2017模拟赛本科试题-风险度量

借鉴于该博客蓝桥杯风险度量_dfs无向图两节点间的所有路径

题目

标题:风险度量

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

思考

由例题可知有两条链路分别为:
1->3->4->5->6
1->3->5->6
由上可知当3和5 站点被破坏后,1与6将无法通信
所以1和5站点为关键站点
这题我采用无向图深度深度优先算法(DFS)找出1到6节点中的所有路径
当路径中除了1和6的其它节点在符合条件的所有路径中出现的次数与路径条数相等时即说明该节点为关键节点

代码

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static int space[] ;     //空间站数组,并判断是否被访问,若访问过则为1否则为0
    public static int route[][] ;   //路径数组表示空间站之间的路径,路径存在即为1否则为0
    public static List<Integer[]> res = new ArrayList<>();  //存放所有符合条件的路径数组
    public static Stack<Integer> stack = new Stack<>(); //用栈表示某条路径
    public static void main(String args[]){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        space = new int[n] ;
        route = new int[n+1][n+1];
        for(int i = 0 ; i < m ; i++){   //输入路径
            int a = scanner.nextInt() ;
            int b = scanner.nextInt() ;
            //表示无向路径
            route[a][b] = 1 ;       
            route[b][a] = 1 ;
        }
        int start = scanner.nextInt();
        int end = scanner.nextInt() ;
        scanner.close();
        dfs(start,end);     //利用dfs找出所有符合条件的路径
        int count[] = new int[n+1] ;
        for(int i = 0 ; i < res.size() ;i++){
            for(int j = 0 ; j < res.get(i).length ; j++){
                count[res.get(i)[j]] ++ ;   //记录节点在所有路径中出现的次数
            }
        }
        int c = 0 ;
        for(int i = 1 ; i < count.length ; i ++){
            if(count[i] == res.size() && i != start && i != end){   //若某个节点出现的次数与路径条数相等则关键节点数+1
                c ++ ;
            }
        }
        System.out.println(c);
    }
    private static void dfs(int start, int end) {
        stack.push(start);  //将首节点入栈
        space[start] = 1 ;  //并将该节点设为以访问状态
        while(true){
            if(start == end){   //搜索完毕
                Integer[] oneRoute = new Integer[stack.size()] ;    //存放该路径的数组
                for(int i = 0 ; i < stack.size() ; i++){
                    oneRoute[i] = stack.get(i) ;    
                }
                res.add(oneRoute) ;//将该路径添加进list中
                stack.pop();    //将栈顶元素弹出
                space[start] = 0 ;  //并设为未访问状态
                break;
            }
            for(int i = 0 ; i < route.length ; i++){
                if(route[start][i] == 1 && space[i] == 0){//搜索下一个未访问的且与当前节点有链路的节点
                    dfs(i,end);
                }
            }
            //搜索完最后的节点了,即到达边界了
            stack.pop();
            space[start] = 0 ;
            break ;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值