题解:P2296 [NOIP2014 提高组] 寻找道路

条件第一步,要能到达 \(t\) 点,建反图跑一遍。记录哪些点可行。

第二步,扫描每个点,若其旁边均为标记过的,说明点的出边所指向的点都直接或间接与终点连通。记录这个点第二次

第三步,在原边枚举每条边,若两个节点均被记录了第二次,加入一个新图,否则扔掉。

对新图进行 BFS 即可。

代码:

#include<bits/stdc++.h>
using namespace std;
int n, m, s, t, vis[10005], can[10005], dis[10005];
vector<int> g[10005], f[10005], h[10005];
void dfs(int u){
    vis[u] = 1;
    for(int i = 0; i < g[u].size(); i ++){
        if(!vis[g[u][i]]){
            dfs(g[u][i]);
        }
    }
}
queue<int> q;
int main(){
    cin >> n >> m;
    for(int i = 1; i <= m; i ++){
        int u, v; cin >> u >> v;
        f[u].push_back(v); g[v].push_back(u);
    }
    cin >> s >> t;
    dfs(t);
    for(int i = 1; i <= n; i ++){
        can[i] = 1;
        for(int j = 0; j < f[i].size(); j ++){
            can[i] = min(can[i], vis[f[i][j]]);
        }
    }
    for(int i = 1; i <= n; i ++){
        for(int j = 0; j < g[i].size(); j ++){
            if(can[i] && can[g[i][j]]) h[g[i][j]].push_back(i);
        }
    }
    for(int i = 1; i <= n; i ++) dis[i] = -1;
    q.push(s); dis[s] = 0;
    while(q.size()){
        int now = q.front(); q.pop();
        for(int i = 0; i < h[now].size(); i ++){
            if(dis[h[now][i]] == -1){
                dis[h[now][i]] = dis[now] + 1;
                q.push(h[now][i]);
            }
        }
    }
    cout << dis[t];
    return 0;
}

posted on   zhangzirui66  阅读(9)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示