LGOJ P2296 【寻找道路】
题目描述
在有向图 \(G\) 中,每条边的长度均为 \(1\),现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件\(1\)的情况下使路径最短。
注意:图 \(G\) 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入格式
第一行有两个用一个空格隔开的整数 \(n\) 和 \(m\),表示图有 \(n\) 个点和\(m\) 条边。
接下来的 \(m\) 行每行 \(2\) 个整数 \(x,y\),之间用一个空格隔开,表示有一条边从点 \(x\) 指向点\(y\)。
最后一行有两个用一个空格隔开的整数 \(s, t\),表示起点为 \(s\),终点为 \(t\)。
输出格式
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出\(-1\)。
输入输出样例
输入 #1
3 2
1 2
2 1
1 3
输出 #1
-1
输入 #2
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
输出 #2
3
说明/提示
解释\(1\):
如上图所示,箭头表示有向道路,圆点表示城市。起点\(1\)与终点\(3\)不连通,所以满足题目描述的路径不存在,故输出\(-1\) 。
解释2:
如上图所示,满足条件的路径为\(1- >3- >4- >5\)。注意点\(2\) 不能在答案路径中,因为点\(2\)连了一条边到点\(6\) ,而点\(6\) 不与终点\(5\) 连通。
【数据范围】
对于\(30\%\)的数据,\(0 < n \le 100\),\(0 < m \le 200\);
对于\(60\%\)的数据,\(0 < n \le 1000\),\(0 < m \le 20000\);
对于\(100\%\)的数据,\(0 < n \le 10000\), \(0 < m \le 200000\),\(0 < x,y,s,t \le n, x,s \ne t\)。
問題の解
思路比较直接:
1° 建反图,从\(t\)开始\(dfs\),以得到所有能到达到\(t\)的点,用\(rc[]\)数组记录。\(rc[u]==1\)表示\(u\)能直接或间接到达\(t\);
//vector<int> RG[N];表示反图
void dfs(int u)
{
rc[u]=1;
for(int i=0;i<RG[u].size();i++)
{
int v=RG[u][i];
if(rc[v]==0)dfs(v);
}
}
2° 探究每一个点\(u\)是否能被选择(能否参与构成路径),用\(sel[]\)数组记录。\(sel[u]==1\)表示\(u\)是可以出现在路径上的点。枚举\(u\)的出边,求\(sel[u]\):
其中,\(v_1,v_2,...v_{end}\)是\(u\)的出边直连的点;\(\&\)是逻辑与运算符;
//vector<int> G[N];表示原图
for(int u=1;u<=n;u++)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
sel[u]&=rc[v];
}
}
3° 对于所有\(sel[vertex]==1\)的点,跑\(Dijkstra\)模板。
完整代码:
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
char c=getchar();int x=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
x=x*10+c-'0';
return x;
}
const int N=10005,M=200005,INF=0x3f3f3f3f;
bool rc[N],GG[N][N],sel[N];
int d[N];
int n,m,s,t;
vector<int> G[N];
vector<int> RG[N];
bool vis[N];
priority_queue< pair<int,int> >Q;
void dfs(int u)
{
rc[u]=1;
for(int i=0;i<RG[u].size();i++)
{
int v=RG[u][i];
if(rc[v]==0)dfs(v);
}
}
void dijk()
{
for(int i=1;i<=n;i++)d[i]=INF;
memset(vis,0,sizeof(vis));
d[s]=0;
Q.push(make_pair(0,s));
if(sel[s]==0)return;
while(!Q.empty())
{
int u=Q.top().second;
Q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(sel[v]&&d[v]>d[u]+1)
{
d[v]=d[u]+1;
Q.push(make_pair(-d[v],v));
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u=read();
int v=read();
if(u==v)continue;
if(GG[u][v])continue;
GG[u][v]=1;
G[u].push_back(v);
RG[v].push_back(u);
}
cin>>s>>t;
dfs(t);
for(int i=1;i<=n;i++)sel[i]=1;
for(int u=1;u<=n;u++)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
sel[u]&=rc[v];
}
}
dijk();
if(d[t]!=INF)cout<<d[t];
else cout<<"-1";
return 0;
}
本文来自博客园,作者:miyasaka,转载请注明原文链接:https://www.cnblogs.com/kion/p/11816157.html