题目描述
有一个邮递员要送东西,邮局在节点 11。他总共要送 n-1n−1 样东西,其目的地分别是节点 22 到节点 nn。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 mm 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n-1n−1 样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,nn 和 mm,表示城市的节点数量和道路数量。
第二行到第 (m+1)(m+1) 行,每行三个整数,u,v,wu,v,w,表示从 uu 到 vv 有一条通过时间为 ww 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
输入输出样例
输入 #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 \leq n \leq 2001≤n≤200。
对于 100\%100% 的数据,1 \leq n \leq 10^31≤n≤103,1 \leq m \leq 10^51≤m≤105,1\leq u,v \leq n1≤u,v≤n,1 \leq w \leq 10^41≤w≤104,输入保证任意两点都能互相到达。
思路:来、回各一次spfa,首先去到的肯定找到的是正确的最短路,而返回的则把所有边转为反方向,找到的最短路在实际上都是反过来的,那么到的最短路就是回的最短路(应该很好接受,因为方法是对的,就是全反过来而已,结果都是对应的)。
#include<bits/stdc++.h>
using namespace std;
//一次来回,首先去到的肯定找到的是正确的最短路,而返回的则把所有边
//转为反方向,找到的最短路在实际上都是反过来的,那么到的最短路就是
//回的最短路(应该很好接受,因为方法是对的,就是全反过来而已,结果有对应)
const int maxn=1e3+5;
int dis[maxn];
bool vis[maxn];
struct edge{
int v,w;
};
vector<edge> edg1[maxn],edg2[maxn];
queue<int> q;
void spfa(int n,int s,bool f)//此题不用考虑环,要考虑的则再搞个cnt数组,然后在每次可以松弛的地方加上个cnt=什么+1即可
{
memset(dis,63,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(auto ed:(f?edg1[u]:edg2[u]))
{
int v=ed.v,w=ed.w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])q.push(v),vis[v]=1;
}
}
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
edg1[u].push_back({v,w});
edg2[v].push_back({u,w});
}
spfa(n,1,1);
int ans=0;
for(int i=1;i<=n;i++)ans+=dis[i];
spfa(n,1,0);
for(int i=1;i<=n;i++)ans+=dis[i];
cout<<ans;
return 0;
}