洛谷 P2296 寻找道路 题解

题面

先反向建边,这样以t为源点一遍bfs即可判断出哪个点不可以到达t点;

然后正向建边,以s为源点再一遍bfs计算距离;对于一个点u枚举其叶子结点v来判断u的子节点是否可以直接或间接到达t;

#include <bits/stdc++.h>
#define cin std::ios::sync_with_stdio(false); cin
#define cout std::ios::sync_with_stdio(false); cout
using namespace std;
struct littlestar{
    int to;
    int nxt;
}star[400010],star2[400010];
int head2[400010],cnt2;
int head[400010],cnt;
inline void add(int u,int v)
{
    star[++cnt].to=v;
    star[cnt].nxt=head[u];
    head[u]=cnt;
}
inline void add2(int u,int v)
{
    star2[++cnt2].to=v;
    star2[cnt2].nxt=head2[u];
    head2[u]=cnt2;
}
int f[200010];
int zhaobaba(int x)
{
    if(f[x]==x){
        return x;
    }
    return f[x]=zhaobaba(f[x]);
}
int n,m;
int bo[100010];
int s,t;
queue<int> q;
int dis[100010],vis[100010];
void bfs()
{
    q.push(t);
    bo[t]=1;
    while(q.size()){
        int u=q.front();
        q.pop();
        for(register int i=head2[u];i;i=star2[i].nxt){
            int v=star2[i].to;
            if(!bo[v]){
                bo[v]=1;
                q.push(v);
            }
        }
    }
}
void bfs2()
{
    while(q.size())  q.pop();
    vis[s]=1;
    dis[s]=0;
    q.push(s);
    while(q.size()){
        register int u=q.front();
        q.pop();
        bool lala=1;
        for(register int i=head[u];i;i=star[i].nxt){
            int v=star[i].to;
            if(!bo[v]) lala=0;
        }
        if(lala==0) continue;
        for(register int i=head[u];i;i=star[i].nxt){
            int v=star[i].to;
            if(!vis[v]){
                vis[v]=1;
                dis[v]=dis[u]+1;
                q.push(v);
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    for(register int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        add(x,y);
        add2(y,x);
    }    
    cin>>s>>t;
    int goal=f[t];
    bfs();
    bfs2();
    cout<<dis[t];
}
原文地址:https://www.cnblogs.com/kamimxr/p/11384950.html