【题解】Luogu[P2296] [NOIP2014 提高组] 寻找道路
很简单的一道图论题。
要在一个有向图上找一条 到 的最短路,要求这条路径上的所有点都满足:该点的所有出边所连点都能到达终点 。
看上去很乱,我们简单分解一下,先在所有点中找到与终点有路径的点集 进行标记,再再所有点中找到其所有出边所连点都被打上标记的点集 。
很容易证明 ,因为对于任意一点 则说明 必可到达与之相连的点 ,其中 ,又因为 可到达 ,所以 必可到达 ,所以 。
于是思路就很明确了,先找到 ,再在 中找 ,最后在 中跑一遍最短路即可。这里因为边权都为 ,跑 01bfs 即可。
这里对于找 ,我们发现直接从起点开始找很难找,我们不妨再建一个反图,从终点开始找,就很好找了。
code#
#include<bits/stdc++.h>
using namespace std;
const int NR=1e4+5;
int n,m;
vector<int>e[NR],g[NR];
int s,t;
bool ct[NR],lt[NR];
int dis[NR];
queue<int>q;
void dfs(int u){
ct[u]=true;
for(int i=0;i<e[u].size();++i){
int v=e[u][i];
if(!ct[v])dfs(v);
}
}
void bfs(){
dis[s]=1,q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
if(u==t){cout<<dis[t]-1;exit(0);}
for(int i=0;i<g[u].size();++i){
int v=g[u][i];
if(lt[v]&&!dis[v])
dis[v]=dis[u]+1,q.push(v);
}
}
}
int main(){
cin>>n>>m;
for(int i=1,u,v;i<=m;++i)
cin>>u>>v,e[v].push_back(u),g[u].push_back(v);
cin>>s>>t;
ct[t]=true,dfs(t);
if(!ct[s]){cout<<-1<<endl;return 0;}
for(int i=1;i<=n;++i)
if(ct[i]){
lt[i]=true;
for(int j=0;j<g[i].size();++j)
if(!ct[g[i][j]]){lt[i]=false;break;}
}
if(!lt[s]){cout<<-1<<endl;return 0;}
bfs();
cout<<-1<<endl;
return 0;
}
作者:agrumestly
出处:https://www.cnblogs.com/agrumestly/p/17600782.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架