【洛谷P1346】电车【最短路】
题目大意:
题目链接:https://www.luogu.org/problemnew/show/P1346
给出一个图,每条边有一个指定方向,但是如果想从这个点到达其它有通路但不是指定方向的点的话,就要改变指定方向并且花费为1。求从到的最小花费。
思路:
这个图没有边权。考虑用指定方向作为边权且跑最短路。
由于如果要到的这个点是指定方向的点的话就不用花费,否则需要花费1,所以很容易想到将所有与这个点相连的点连边,若本来就是指定方向就边权为0,否则边权为1。
那么当走了一条不是指定方向的路之后,是否需要更改指定方向呢?
很明显是不用的。
假设我们走过了这个点之后不再回到这个点,那么是否更改就不会影响结果。
假设我们走过了这个点之后再次回到这个点,那么相当于绕了一个环,在没有负边权的情况下,绕一个环肯定不会得到更优解,所以还不如不绕环,也就是还不如不回到这个点,即最优解的每个点最多只经过一次。
很小,即可。
代码:
#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;
}