zoukankan      html  css  js  c++  java
  • 问题 1433: [蓝桥杯] [历届试题] 危险系数 (并查集)

    题目链接

    **问题描述 **
    抗日战争时期,冀中平原的地道战曾发挥重要作用。
    地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。
    我们来定义一个危险系数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

    分析:
    简单的并查集的应用,首先用一次并查集判断一下询问的两点是否连通,不连通的话直接输出-1,否则对一任意的一个不是询问点的点,我们要将这个点以及所有的与它直接相连的边去点之后再判断整个图的连通性,如果此时两个询问点不联通的话,那么相当于这个点为关键点。

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    using namespace std;
    int n,m;
    int road[2002][2002];
    int pre[2002];
    void init()
    {
        for(int i=1; i<=n; i++)
            pre[i]=i;
    }
    
    int find_pre(int root)
    {
        int son,tmp;
        son=root;
        while(root!=pre[root])
            root=pre[root];
        while(son!=root) ///压缩路径,将所有节点的父节点都变换成当前的根节点,这样在以后再找的时候就会节省时间
        {
            tmp=pre[son];
            pre[son]=root;
            son=tmp;
        }
        return root;
    }
    
    void unin(int x,int y)
    {
        int px=find_pre(x);
        int py=find_pre(y);
        if(px!=py)
            pre[px]=py;
    }
    
    int main()
    {
        int a,b;
        while(~scanf("%d%d",&n,&m))
        {
            memset(road,0,sizeof(road));
            for(int i=0; i<m; i++)
            {
                scanf("%d%d",&a,&b);
                road[a][b]=road[b][a]=1;//标记两点间有路径
                unin(a,b);
            }
            int st,ed;
            int ans=0;
            scanf("%d%d",&st,&ed);
            if(find_pre(st)!=find_pre(ed))//两个询问点本来就不连通
                printf("-1
    ");
            else
            {
                for(int k=1; k<=n; k++)
                {
                    init();
                    if(k!=st&&k!=ed)//要遍历所有的非询问点
                    {
                        for(int i=1; i<=n; i++)
                        {
                            for(int j=1; j<=n; j++)
                            {
                                if(road[i][j]==1&&i!=k&&j!=k)
                                {
                                    unin(i,j);
                                }
                            }
                        }
                        if(find_pre(st)!=find_pre(ed))
                            ans++;
                    }
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    WebEssentials 在vs2013 update5安装报错的解决方法.
    提高代码质量系列之三:我是怎么设计函数的?
    ValueInjecter----最好用的OOM(以微信消息转对象举例)
    我的第一个python程序--给2.x的print代码加上括号
    提高代码质量系列之二:重构小技巧——if篇
    提高代码质量系列之一:尽可能少写注释.
    Two-machine debugging
    12306个人敏感信息泄露
    纯手工秒杀VM,SE等虚拟机Handle
    2014版QQ个性显IP(源码+Bin)
  • 原文地址:https://www.cnblogs.com/cmmdc/p/8618753.html
Copyright © 2011-2022 走看看