题目描述
有一个邮递员要送东西,邮局在节点 11。他总共要送 n-1n−1 样东西,其目的地分别是节点 22 到节点 nn。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 mm 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n-1n−1 样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。
第二行到第 (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% 的数据,1≤n≤200。
对于 100% 的数据,1≤n≤10^3,1≤m≤10^5,1≤u,v≤n,1≤w≤10^4,输入保证任意两点都能互相到达。
题解:
第一眼看到这个题 哇!我只要开1次SPFA就能A了,这题真水!
当我看题目时:哇!每次只能带1个信件,要回去拿!也就n次SPFA吧!
这时我看到了数据范围,N次SPFA一定炸
于是我想到了一个好方法,用1次SPFA找各个点到点1的最短路
然后开一个反向图,再用SPFA搜一下点1到反向图各个点的最短路
这时我们发现反向图中点1到各个点的最短路就是普通图中各个点到点1的最短路!!!
话不多说上代码
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
struct node{
int to;
int data;
};
vector<node>map[1005];
vector<node>mp[1005];
int low[1005];
bool vis[1005];
int m,n;
void spfa(int s){
memset(vis,false,sizeof(vis));
memset(low,INF,sizeof(low));
queue<int>Q;
int start,next;
start=s;low[s]=0;vis[s]=true;
Q.push(start);
while(!Q.empty()){
start=Q.front();
Q.pop();
for(int i=0;i<map[start].size();i++){
next=map[start][i].to;
//cout<<next<<endl;
if(low[next]>low[start]+map[start][i].data){
low[next]=low[start]+map[start][i].data;
Q.push(next);
}
}
vis[start]=true;
}
}
void spfa1(int s){
memset(vis,false,sizeof(vis));
memset(low,INF,sizeof(low));
queue<int>Q;
int start,next;
start=s;low[s]=0;vis[s]=true;
Q.push(start);
while(!Q.empty()){
start=Q.front();
Q.pop();
for(int i=0;i<mp[start].size();i++){
next=mp[start][i].to;
//cout<<next<<endl;
if(low[next]>low[start]+mp[start][i].data){
low[next]=low[start]+mp[start][i].data;
Q.push(next);
}
}
vis[start]=true;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v,w;
node temp;
scanf("%d%d%d",&u,&v,&w);
temp.to=v;temp.data=w;
map[u].push_back(temp);
temp.to=u;temp.data=w;
mp[v].push_back(temp);
}
spfa(1);
long long int ans=0;//记住千万记得初始化为0
for(int i=1;i<=n;i++) ans+=low[i];
spfa1(1);
for(int i=1;i<=n;i++) ans+=low[i];
printf("%lld\n",ans);
}