P8604 [蓝桥杯 2013 国 C] 危险系数 题解

· · 题解

题目

在审完题之后,我们会发现:n1000 以内,所以一个 O(n^2) 的复杂度是可以被接受的。既然这样,就让我们请出老朋友:暴力枚举吧!

怎么枚举呢?我们就将每一个点都设置为 z,看能否从 x 走到 y。为了防止超时,这里使用时间复杂度更低的 BFS 判断联通,只要搜到了 y(从 x),一定有路。搜不到的数量就是答案了。

注意事项:

代码及解释都在下面了哦。

#include<bits/stdc++.h>
using namespace std;
bool lu[1005][1005],lu2[1005][1005];//邻接矩阵和临时存储(1有0无边)
int x,y,n,m,cnt;//cnt计数,其他题面有
queue<int>ans;
bool f(int z){//使用BFS来进行判断
    while(!ans.empty())ans.pop();
    ans.push(x);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            lu2[i][j]=lu[i][j];//防止原矩阵被破坏
        }
    }
    //ans里的是起点
    while(!ans.empty()){
        for(int i=1;i<=n;i++){//然后枚举终点
            if(lu2[ans.front()][i]==1&&i!=z&&ans.front()!=z){//有路且不含Z
                if(i==y)return 0;//优化,否则#5TLE
                ans.push(i);
                lu2[ans.front()][i]=0;
                lu2[i][ans.front()]=0;
            }
        }
        ans.pop();
    }
    return 1;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        cin>>x>>y;
        lu[x][y]=1;
        lu[y][x]=1;//地道是无向的
    }
    cin>>x>>y;
    if(f(0)==1){//不删都到不了的情况
        cout<<-1;
        return 0;
    }
    for(int z=1;z<=n;z++){//枚举删除点
        if(z!=x&&z!=y){
            if(f(z)){
                cnt++;
            }
        }
    }
    cout<<cnt;
    return 0;
}

谢谢观看。