邮递员送信——最短路
有一个邮递员要送东西,邮局在结点 1。他总共要送 N-1 样东西,其目的地分别是 2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 M 条道路,通过每条道路需要一定的时间。 这个邮递员每次只能带一样东西。 求送完这 N-1 样东西平且最终回到邮局最少需要多少时间。
输入格式:
输入文件第一行包含一个正整数 N 和 M; 接下来 M 行, 每行三个正整数 U、 V、 W, 表示该条道路为从 U 到 V 的, 且通过这条道路 需要 W 的时间。满足 1≤U, V≤N,1≤W≤10000, 输入保证任意两点都能互相到达。
输出格式:
输出仅一行,包含一个整数,为最少需要的时间。
限制:
对于 30%的数据,满足 1≤N≤200。 对于 100%的数据,满足 1≤N≤1000,1≤M≤100000。
样例 1 :
输入: 5 10 2 3 5 1 5 5 3 5 6 1 2 8 1 3 8 5 3 4 4 1 8 4 5 3 3 5 6 5 4 2
输出: 83
解题思路:
这道题我一开始是用Floyd写的,只能通过部分数据,然后其他数据超时。然后想了很长时间还是没想出来(可能是智商问题吧
~_~)。然后我看了一些大佬的代码,终于懂了,就是用两次Dijkstra算法,这个题意思是求起点到每个点的最短距离,然后再求每个点到起点的距离。最后输出这些距离的和。(还是一道水题);
下面看代码:
#include <stdio.h>
int a[1001][1001];
int dis[1001],book1[1001];//book1,book2用来标记;
int book2[1001];
int main()
{
int n,m,u,v,w,i,t,j,inf=99999999,sum=0,min,tt;
scanf("%d%d",&n,&m);//输入数据
for(i=1;i<=n;i++)//建图
for(j=1;j<=n;j++)
if(i==j) a[i][j]=0;
else a[i][j]=inf;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
if(a[u][v]>w)//注意这里,数据有重边的
a[u][v]=w;
}
for(i=1;i<=n;i++)//初始化dis数组
dis[i]=a[1][i];
book1[1]=1;//标记起点
//核心,Dijkstra算法
for(i=1;i<=n-1;i++)//送信
{
min=inf;
for(j=1;j<=n;j++)
{
if(min>dis[j]&&book1[j]==0)//找出距离起点最近的点
{
min=dis[j];
t=j;
}
}
book1[t]=1;//标记这个点
for(j=1;j<=n;j++)//寻找距离t点最近的点
{
if(a[t][j]<inf)
if(dis[j]>dis[t]+a[t][j])
{
dis[j]=dis[t]+a[t][j];
}
}
}
for(i=1;i<=n;i++)
if(dis[i]!=inf) sum+=dis[i];//将送信所用时间加起来
book2[1]=1;//再次执行Dijkstra算法,回邮局
for(i=1;i<=n;i++)//先将图翻转
for(j=1;j<i;j++)
{
tt=a[i][j];
a[i][j]=a[j][i];
a[j][i]=tt;
}
for(i=1;i<=n;i++)//数据初始化
dis[i]=a[1][i];
for(i=1;i<=n-1;i++)
{
min=inf;
for(j=1;j<=n;j++)
{
if(min>dis[j]&&book2[j]==0)
{
min=dis[j];
t=j;
}
}
book2[t]=1;
for(j=1;j<=n;j++)
{
if(a[t][j]<inf)
if(dis[j]>dis[t]+a[t][j])
dis[j]=dis[t]+a[t][j];
}
}
for(i=1;i<=n;i++)
if(dis[i]!=inf) sum+=dis[i];//把回邮局用的时间加起来
printf("%d\n",sum);
return 0;
}