洛谷 2296_寻找道路_spfa+dfs

发布于 2019-05-16  7 次阅读


题目描述

在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:

1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。

2 .在满足条件1 的情况下使路径最短。

注意:图G 中可能存在重边和自环,题目保证终点没有出边。

请你输出符合条件的路径的长度。


思路

题目的意思是最短路上的点的所有出度都必须可以走到终点

首先从终点进行一次dfs,标记出那些点可以走到,然后spfa一下,每走一个点都暴力枚举全部出度,判断一下就可以了


#include 
#include 
#include 
#define maxn 200001
#define INF 2147483647
using namespace std;
int l=0,s;
struct arr 
{ 
    int x,y,w,next;   
};
int x,y,z,e;
arr edge[maxn],edge1[maxn];
int ls[maxn],ls1[maxn];
int state[maxn];
bool exits[maxn];
int f[maxn],c[maxn],fl[maxn];
int dfs(int x)
{
    if (x==0) return 0;
    int i=ls1[x];
    while (i!=0)
    {   
        if(fl[edge1[i].y]==0)
        {
            f[edge1[i].y]=1;
            fl[edge1[i].y]=1;
            dfs(edge1[i].y);
        }
        i=edge1[i].next;
    }
    return 0;
}
int spfa()
{
    int i;
    queue  t;
    t.push(s);
    state[s]=0;
    exits[s]=true;
    do
    {
        int tt=t.front();
        t.pop();
        i=ls[tt];
        int j=ls[tt],ff=1;
        while (j!=0)
        {
            if (f[edge[j].y]==0) ff=0;
            j=edge[j].next;
        }
        while (i!=0&&ff==1) 
        {
            if (state[edge[i].x]+edge[i].w0&&f[edge[i].x]>0)
            {
                state[edge[i].y]=state[edge[i].x]+edge[i].w;
                if (exits[edge[i].y]==false)
                {
                    t.push(edge[i].y);
                    exits[edge[i].y]=true;
                }
            }
            i=edge[i].next;
        }
        exits[tt]=false;
    }
    while (!t.empty());
}
int main()
{
    int j,k,n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        edge[++l]=(arr){x,y,1,ls[x]};
        edge1[l]=(arr){y,x,1,ls1[y]};
        c[x]++;
        ls[x]=l;
        ls1[y]=l;
    }
    for (int i=1;i
]]>