洛谷P1346-电车【日常图论,最短路,SPFA】

题目

一个有向图,每个点有个默认方向和若干个其他方向,走默认方向权值为0,其他方向权值为1,求最短路

输入

3 2 1(3个点,点2到点1)
2 2 3(2个点,起点为1,2为默认点,3为其他点)
2 3 1(2个点,起点为2,3为默认点,1为其他点)
2 1 2

输出

0


解题思路

其实就像我题目说的那样默认方向权值为0,其他方向权值为1,求最短路。这里用SPFA算法。


代码

#include
using namespace std;
struct woc{
    int next,x,y,w;
};//日常邻接表
woc a[50001];
int xx,yy,n,m,k,state[10001],ls[10001],t,head,tail,f[10001],star,over;
bool v[10001];
int main()
{
    scanf("%d%d%d",&n,&star,&over);
    state[1]=1;
    int u=0;    
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&xx);
        for (int j=1;j<=xx;j++)
        {
            scanf("%d",&yy);
            if (j==1) a[++u].w=0;
            else a[++u].w=1;//判断默认方向
            a[u].next=ls[i];
            ls[i]=u;
            a[u].x=i;
            a[u].y=yy;//邻接表
        }
    }   
    for (int i=1;i<=n;i++) f[i]=2147483647;
    head=0;
    tail=1;
    state[1]=star;
    v[state[1]]=true;
    f[star]=0;//初始化
    while (head!=tail)
    {
        head++;//出队
        head=(head-1)%n+1;//循环队列
        t=ls[state[head]];//读边
        while (t!=0)
        {
            if (f[a[t].x]+a[t].w//松弛
                if (!v[a[t].y])
                {
                    tail++;//入队
                    tail=(tail-1)%n+1;//循环队列
                    state[tail]=a[t].y;
                    v[a[t].y]=true;//标记
                }
            }
            t=a[t].next;//读下一条边
        }
        v[state[head]]=false;//解封
    }
    if (f[over]==2147483647) printf("-1");//如果无解
    else printf("%d\n",f[over]);
}

你可能感兴趣的:(图论)