LGOJ P2296 寻找道路
Posted #include
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LGOJ P2296 寻找道路相关的知识,希望对你有一定的参考价值。
思路比较直接:
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]\):
\[
sel[u]=rc[v_1] \& rc[v_2] \&...\&rc[v_{end}].
\]
其中,\(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;
}
以上是关于LGOJ P2296 寻找道路的主要内容,如果未能解决你的问题,请参考以下文章