【洛谷P1346】电车【最短路】

题目大意:

题目链接:https://www.luogu.org/problemnew/show/P1346
给出一个图,每条边有一个指定方向,但是如果想从这个点到达其它有通路但不是指定方向的点的话,就要改变指定方向并且花费为1。求从sstt的最小花费。


思路:

这个图没有边权。考虑用指定方向作为边权且跑最短路。
由于如果要到的这个点是指定方向的点的话就不用花费,否则需要花费1,所以很容易想到将所有与这个点相连的点连边,若本来就是指定方向就边权为0,否则边权为1
那么当走了一条不是指定方向的路之后,是否需要更改指定方向呢?
很明显是不用的。
假设我们走过了这个点之后不再回到这个点,那么是否更改就不会影响结果。
假设我们走过了这个点之后再次回到这个点,那么相当于绕了一个环,在没有负边权的情况下,绕一个环肯定不会得到更优解,所以还不如不绕环,也就是还不如不回到这个点,即最优解的每个点最多只经过一次。
nn很小,FloydFloyd即可。


代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int n,s,t,m,x,a[301][301];

int main()
{
    scanf("%d%d%d",&n,&s,&t);
    for (int i=1;i<=300;i++)
     for (int j=1;j<=300;j++) 
      if (i!=j) a[i][j]=99999999;  //初始化
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&m);
        if(!m) continue;
        scanf("%d",&x);
        a[i][x]=0;  //存图
        m--;
        while (m--)
        {
            scanf("%d",&x);
            a[i][x]=1;
        }
    }
    for (int k=1;k<=n;k++)
     for (int i=1;i<=n;i++)
      for (int j=1;j<=n;j++)  //Floyd
       if (i!=j&&j!=k&&k!=i)
        a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
    if (a[s][t]<99999999)printf("%d\n",a[s][t]);
     else printf("-1");
    return 0;
}
原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998620.html