P2296 [NOIP2014 提高组] 寻找道路
① 自己指向的节点都可以到达终点。
② 自己可以到达终点的点。
③ 普通的点。
那么题目需要的就是:
由①组成的连接了起点和终点的最短路径。
思路:
显然③包含②,②包含①。
那么我们就先通过③求出所有的②,再通过②求出①。
最后再来一遍BFS就能求出最短路径了。
步骤:
1.读入数据,并建立正向和反向边。
2.从终点反向BFS,求出所有的②。
3.对每个点判断是否满足①。
4.从起点正向BFS,只经过①点,求出最短路径。
数组解释:
1.inroad 表示是否为 ①
2.can 表示是否为 ②
3.dis 表示距离起点的距离,计算长度用,
4.side 正向边
5.edis 反向边
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<bits/stdc++.h> #define ll long long #define ddd printf("-----------------debug\n"); using namespace std; const int maxn=2e5+10; int n,m,s,t; int head1[maxn],to1[maxn],nxt1[maxn],cnt1; int head2[maxn],to2[maxn],nxt2[maxn],cnt2; int can[maxn],inroad[maxn],dis[maxn]; void add1(int u,int v){ to1[++cnt1]=v; nxt1[cnt1]=head1[u]; head1[u]=cnt1; } void add2(int u,int v){ to2[++cnt2]=v; nxt2[cnt2]=head2[u]; head2[u]=cnt2; } int main() { ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; add1(x,y);add2(y,x); } cin>>s>>t; can[t]=1; queue<int> q; q.push(t); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head2[u];i;i=nxt2[i]) { int v=to2[i]; if(can[v]) continue; can[v]=1; q.push(v); } } if(can[s]==0){ cout<<"-1"<<endl; return 0;} for(int i=1;i<=n;i++) { if(can[i]) { inroad[i]=1; for(int j=head1[i];j;j=nxt1[j]) { int v=to1[j]; if(can[v]==0) inroad[i]=0; } } } if(inroad[s]==0){ cout<<"-1"<<endl; return 0;} queue<int> qq; qq.push(s); dis[s]=0; while(!qq.empty()) { int u=qq.front(); qq.pop(); if(u==t){ cout<<dis[t]<<endl; return 0;} for(int i=head1[u];i;i=nxt1[i]) { int v=to1[i]; if(inroad[v]==0||dis[v]) continue; dis[v]=dis[u]+1; qq.push(v); } } return 0; }

浙公网安备 33010602011771号