• 九度 1495:关键点(图论)


    题目描述:

    在一个无权图中,两个节点间的最短距离可以看成从一个节点出发到达另一个节点至少需要经过的边的个数。
    同时,任意两个节点间的最短路径可能有多条,使得从一个节点出发可以有多条最短路径可以选择,并且沿着这些路径到达目标节点所经过的边的个数都是一样的。
    但是在图中有那么一些特殊的节点,如果去除这些点,那么从某个初始节点到某个终止节点的最短路径长度要么变长,要么这两个节点变得不连通。这些点被称为最短路径上的关键点。
    现给定一个无权图,以及起始节点和终止节点,要求输出该图上,这对节点间最短路径上的关键点数目。

    思路

    1. 起初把题目想简单了, 以为一遍 BFS 就能得到正解, 用案例跑了下没报错就直接提交了, 结果 WA

    2. 看了解题报告发现自己 MISS 掉了很多特殊情况, 比如某个节点时关键节点但是还有与它同层但无意义的其他节点, 这就需要两遍 BFS

    3. 第一遍 BFS 记录节点所在的层, 第二遍 BFS 只对层数小于当前节点的邻接节点遍历

    代码

    #include <iostream>
    #include <stdio.h>
    #include <deque>
    #include <vector>
    #include <memory.h>
    using namespace std;
    
    vector<int> graph[10005];
    bool visited[10005];
    int level[10005];
    int n, m, s, t;
    
    
    void firstPass() {
        deque<int> queue;
        queue.push_back(s);
    
        visited[s] = 1;
        int depth = 1;
        level[s] = depth ++;
    
        int curlevel = 1, nextlevel = 0;
        while(!queue.empty()) {
            int p = queue.front();
            queue.pop_front();
            curlevel --;
    
            if(p == t)
                break;
    
            for(int i = 0; i < graph[p].size(); i ++) {
                int sp = graph[p][i];
                if(visited[sp]) continue;
                visited[sp] = 1;
                queue.push_back(sp);
                nextlevel ++;
                level[sp] = depth;
            }
    
            if(curlevel == 0) {
                curlevel = nextlevel;
                nextlevel = 0;
                depth ++;
            }
        }
    }
    
    int secondPass() {
        memset(visited, 0, sizeof(visited));
        deque<int> queue;
        queue.push_back(t);
        visited[t] = 1;
        int cnt = 0;
    
        while(!queue.empty()) {
            int p = queue.front();
            queue.pop_front();
    
            if(queue.size() == 0)
                cnt ++;
    
            if(p == s)
                break;
    
            for(int i = 0; i < graph[p].size(); i ++) {
                int sp = graph[p][i];
                if(level[sp] >= level[p] || visited[sp]) continue;
    
                queue.push_back(sp);
                visited[sp] = 1;
                
            }
        }
        return max(cnt-2, 0);
    }
    int main() {
        
        while(scanf("%d%d%d%d", &n, &m, &s, &t) != EOF) {
    
            memset(level, 0x3f, sizeof(level));
            memset(visited, 0, sizeof(visited));
    
            for(int i = 0; i < n+3; i ++)
                graph[i].clear();
    
            for(int i = 0; i < m; i ++) {
                int fm, to;
                scanf("%d%d", &fm, &to);
                graph[fm].push_back(to);
                graph[to].push_back(fm);
            }
    
            firstPass();
            cout << secondPass() << endl;
            
        }
    
        return 0;
    }
  • 相关阅读:
    perf脚本示例
    pacman安装时允许覆盖文件
    uniapp 使用重启方法后页面卡在启动页的解决方法
    yarn global add 后找不到命令
    讯飞语音 aiui集成
    Pad登录不上网的问题解决方案
    Python 统计指定目录下文件夹的数量(不包含文件)【转】
    tensorflow中使用Adam出现name ‘Adam‘ is not defined【转】
    unet神经网络报错‘Keyword argument not understood:‘,‘input‘解决方法【转】
    Blender中用pip安装包的办法
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3593887.html
Copyright © 2020-2023  润新知