今天折腾了那么久又只有一个题的题解QAQ
先看看题吧
有一个邮递员要送东西,邮局在节点 11。他总共要送 �−1n−1 样东西,其目的地分别是节点 22 到节点 �n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 �m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 �−1n−1 样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,�n 和 �m,表示城市的节点数量和道路数量。
第二行到第 (�+1)(m+1) 行,每行三个整数,�,�,�u,v,w,表示从 �u 到 �v 有一条通过时间为 �w 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
输入输出样例
输入 #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
输出 #1复制
83
说明/提示
对于 30%30% 的数据,1≤�≤2001≤n≤200。
对于 100%100% 的数据,1≤�≤1031≤n≤103,1≤�≤1051≤m≤105,1≤�,�≤�1≤u,v≤n,1≤�≤1041≤w≤104,输入保证任意两点都能互相到达。
刚开始看题的时候真的感觉好开心,这和上面那个题目没啥区别,我正开开心心的把上一题的代码打上去一输入数据发现算不出来83哈哈,仔细一看题发现还要返回来回来我想就乘个二吧,但是手算发现还是到不了八十三,这时候我才开始认真对待这个题目,实在想不明白,难道是回来的时候和去的路线不太一样?就很迷茫,迷茫时该怎么办这时候就要画图了::
简单画了一个图是这样,然后我就在去看了一下题解,才顿时明白,举个例子在这主要是理解题目的这段话:
由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 �m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。
是我想复杂了,本来我以为回来的时候箭头翻转,然后最短的就是按原路返回,简直是大错特错,路当然不会因为一个邮递员的通过而去变化它的通行方向,而这里我们之所以要将这些进行翻转是为了将多元化的问题单元化,全部都转化为一到各个点的最短路径。
#include<stdio.h>
int a[1005][1005],dis[1005],i,j;
#define INF 1e9;
void init(int n)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i!=j)
a[i][j]=INF;//i==j就为零否则则为无穷大
}
}
}
void dij(int n)//经典的单元最短路径代码
{
int f[1005]={0};
f[1]=1;
int v;
for(i=1;i<n;i++)
{
int min=INF;
for(j=1;j<=n;j++)
{
if(!f[j]&&min>dis[j])
{
min=dis[j];
v=j;
}
}
f[v]=1;
for(j=1;j<=n;j++)
{
if(!f[j]&&a[v][j]+dis[v]<dis[j])
{
dis[j]=a[v][j]+dis[v];
}
}
}
}
void fan(int n)
{
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)//反转,也就是将所以箭头的方向调转,方便将回来时各个点到一的最短路径转化为一到各个点的最短路径;
{
int t=0;
t=a[i][j];
a[i][j]=a[j][i];
a[j][i]=t;
}
}
}
int minn(int x,int y)
{
return (x>y)?y:x;
}
int main()
{
int n,m,x,y,z;
scanf("%d %d",&n,&m);
init(n);
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
a[x][y]=minn(a[x][y],z);//注意这里忒重要了,可以保证多次输入的相同起终点里取最短路。
}
for(i=1;i<=n;i++)
{
dis[i]=a[1][i];
}
dij(n);
int ans;
for(i=1;i<=n;i++)
{
ans+=dis[i];
}
fan(n);
for(i=1;i<=n;i++)
{
dis[i]=a[1][i];//刚开始我一直没明白为什么只变一个,其实这里它是后来会全部都更新一遍的,不重新初始化也没关系。
}
dij(n);
for(i=1;i<=n;i++)
{
ans+=dis[i];
}
printf("%d\n",ans);
return 0;
}
首先这还是一个最短路径的题,所以我们可以将最短路径的有关代码准备好,并编制一个函数。
小结:这个题目的总体思想就是求两遍最短路径,运用反转将回来时也变成单源最短路。这里由于一定会有到某个点的路所以对dis没有很大的要求,但是有些题目里面可能是不会有路到某点的,这时候就要设置足够大的dis来装inf无穷大了。
有些人或许生来就有翅膀,也有些人选择靠自己的力量飞翔,有些人失败后就永远趴伏在泥泞里,也有些人,就算历经波折,也要翱翔在蓝天之上。