题目链接:落谷P1629
题目描述
有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。
输入输出格式
输入格式:
第一行包括两个整数N和M。
第2到第M+1行,每行三个数字U、V、W,表示从A到B有一条需要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
输出样例#1:
83
题目摘要:求出点1到每个点的距离和每个点到点1的距离,最后再全部加起来。
怎么做呢?
我们首先一定可以想到用多源最短路径 Floyd 求出每个点之间的距离。但是我们可以看一下数据范围,如果用O(n^3)的时间复杂度,一定会超时。同时,用Floyd是很浪费的,因为我们不需要其他点到其他点的距离,我们只需要求出其他点到点1的距离,所以很明显Floyd不行,同时也不能单源最短路用N次。。。。。
怎么解决呢?
首先我们可以用一次单源最短路(这里我用spfa)求出点1到其他点的最短路径,然后建立反向边,求点1到其他点的最短路径,实际上就是求出了其他点到点1的最短路径
重点
建立反向边,求点1到其他点的最短路径,实际上就是求出了其他点到点1的最短路径
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m,dst1[N],dst2[N],res;
vector<int> v1[N],v2[N],v3[N],v4[N];
void spfa(vector<int> v1[],vector<int> v2[],int dst[])
{
queue<int> q;
int isqueue[N];
memset(isqueue,0,sizeof(isqueue));
q.push(1);
isqueue[1]=1;
while(q.size())
{
int u=q.front();
q.pop();
isqueue[u]=0;
for(int i=0;i<v1[u].size();i++)
{
int v=v1[u][i];
int w=v2[u][i];
if(dst[v]>dst[u]+w)
{
dst[v]=dst[u]+w;
if(!isqueue[v])
{
q.push(v);
isqueue[v]=1;
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=2;i<=n;i++) dst1[i]=dst2[i]=0x3f3f3f3f;
while(m--)
{
int u,v,w;
cin>>u>>v>>w;
v1[u].push_back(v);
v3[v].push_back(u);
v2[u].push_back(w);
v4[v].push_back(w);
}
spfa(v1,v2,dst1);
spfa(v3,v4,dst2);
for(int i=2;i<=n;i++) res+=dst1[i]+dst2[i];
cout<<res<<endl;
return 0;
}