寻找道路

https://www.luogu.org/problemnew/show/P2296

题目很简单,但竟然没一遍A,基础不行啊...

做法很显然,反向建边看哪些点和终点连通,再看哪些点合法能被走,最后正向dfs一次就行

然而没一遍A,是因为bfs的时候vis和ok的处理有问题(看代码

应该在找到节点之后,立即对其进行处理。而不应该在弹出队列的时候对节点进行处理

一个教训吧

0.5h

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch  = getchar();
    }
    return ans * op;
}
const int maxn = 1e5 + 5;
struct node
{
    int to,next,cost;
}e[maxn << 1],rev[maxn << 1];
int fir[maxn],alloc,r_fir[maxn],r_alloc;
void adde(int u,int v)
{
    e[++alloc].next = fir[u];
    fir[u] = alloc;
    e[alloc].to = v;
    swap(u,v);
    rev[++r_alloc].next = r_fir[u];
    r_fir[u] = r_alloc;
    rev[r_alloc].to = v;
}
bool ok[maxn],vis[maxn],con[maxn];
int n,m,s,t;
void mark_rev()
{
    queue<int> q;
    q.push(t);
    vis[t] = 1,ok[t] = 1;
    memset(vis,0,sizeof(vis));
    while(q.size())
    {
        int u = q.front();
        q.pop();
        for(int i = r_fir[u];i;i = rev[i].next)
        {
            int v = rev[i].to;
            if(vis[v]) continue;
            vis[v] = ok[v] = 1;
            q.push(v);
        }
    }
    for(int u = 1;u <= n;u++)
    {
        bool flag = 0;
        for(int i = fir[u];i;i = e[i].next)
        {
            int v = e[i].to;
            if(ok[v] == 0) { con[u] = 0; flag = 1; break; }
        }
        if(flag == 0) con[u] = 1;
    }
}
int dis[maxn];
void solve()
{
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(s);
    dis[s] = 0;
    vis[s] = 1;
    while(q.size())
    {
        int u = q.front();
        q.pop();
        for(int i = fir[u];i;i = e[i].next)
        {
            int v = e[i].to;
            if(vis[v] || con[v] == 0) continue;            
            dis[v] = dis[u] + 1;
            vis[v] = 1;
            q.push(v);
        }
    }
    if(dis[t] == 0) printf("-1");
    else printf("%d",dis[t]);
}    
int main()
{
    n = read(),m = read();
    for(int i = 1;i <= m;i++)
    {
        int u = read(),v = read();
        if(u == v) continue;
        adde(u,v);
    }
    s = read(),t = read();
    mark_rev();
    solve();
}
原文地址:https://www.cnblogs.com/LM-LBG/p/10697570.html