【 NOIP 2014 】【 Day2 T2 】【 寻找道路 】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/violinlove/article/details/81706480

luogu传送门

已经开始上课了,心情总是不平静的,无论是作业还是竞赛,还差好大一截

这道题是图论题,我首先想建反向图 + Tarjan缩点 + 跑dfs标记可到达的点且搜到起点便停止 + 更新不可到达的点 + Spfa

然后 华丽丽的 WA

首先 Tarjan 缩点便是想错了(至此还没有掌握 图论 的套路,决定去刷套题了 ) 会将 路径长度 缩短

搜到 起点停止 -> 没有道理

更新点时 没想到 后效性 问题 ( 更深入的问题 )

正确做法:

建反向图 + 找到所有可到达的点 & 标记 + 对于一开始 就 不可到达的点 更新 原先可到达的点标记为不可遍历到( 注意后效性 ) + Spfa 跑一遍最短路(对于不可到达的点 跳过 即可 )

至于后效性,只是粗浅的理解了一下,此处____________挖个坑!!

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define inf 0x3f3f3f3f

using namespace std;

inline int wread(){
    char c(getchar ());int wans (0),flag(1);
    while (c<'0' ||c>'9'){if (c=='-') flag=-1; c=getchar ();}
    while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
    return wans*=flag;
} 


int n,m;
int K,hed[10005];
struct node{int u,v,nxt;}e[200008];
void ad (int u,int v){e[++K]=(node){u,v,hed[u]};hed[u]=K;}
int S_1,T_1;

bool vis[10005];

void dfs (int x){
    if(vis[x])	return ;
    vis[x]=true;
    
    for (int i(hed[x]);i;i=e[i].nxt){
        int v(e[i].v);
        dfs(v);
    }
}

int dis[10005], que[1000005];
bool inss[10005],ta[10005];

int main (){
    n=wread(),m=wread();
    for (int i(1);i<=m;++i){
        int u(wread()),v(wread());
        if (u==v)	continue;
        ad(v,u);
    }
    
    S_1=wread(),T_1=wread();
    // 标记 
    dfs(T_1);
    //更新 不可遍历 
    vis[S_1]=vis[T_1]=1;
    
    memcpy(ta,vis,sizeof ta);//拷贝一份,避免后效性 
    for (int i(1);i<=n;++i){
        if (i==S_1 || i==T_1 ) continue;
        if (ta[i])	continue;
        for (int j(hed[i]);j;j=e[j].nxt){
            int v(e[j].v);
            if (v==i || v==S_1 || v==T_1)	continue;
            if (vis[v])	vis[v]=false;
        }
    }
    
    vis[S_1]=vis[T_1]=1;
    
    //Spfa 
    memset (dis,inf,sizeof dis);
    int h(0),t(0);
    que[++h]=T_1;
    dis[T_1]=0;
    inss[T_1]=true;
    while (t<h){
        int x(que[++t]);inss[x]=false;
        for (int i(hed[x]);i;i=e[i].nxt){
            int v(e[i].v);
            if (!vis[v])	continue;
            if (dis[v] > dis[x] + 1 )	dis[v]=dis[x]+1;
            else continue;
            if (!inss[v])	inss[v]=true,que[++h]=v;
        }	
    }
    
    if (dis[S_1]==inf)	puts("-1");
    else printf("%d\n",dis[S_1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/violinlove/article/details/81706480
今日推荐