P1629 邮递员送信
- 题目描述
有一个邮递员要送东西,邮局在节点 1。他总共要送 n-1 样东西,其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n-1样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。
第二行到第 (m+1)行,每行三个整数,u,v,w表示从u 到 v有一条通过时间为 w 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
- 思路
- 从邮局到各个点,以1为原点的单源最短路径
- 从各个点到1的最短路径 ,反向建图即可
- 代码(AC code
链式前向星+优先队列+dijkstra
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1e3*2+10;
const int maxm=1e5*2+10;
int head[maxm];
int n,m;
int dis[maxn];
bool vl[maxn];
long long ans=0;
int cnt=0;
struct node{int next,v,w;}e[maxm];
void ad(int u,int v,int w){e[++cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;}
void dj(int x){
//初始化
memset(dis,0x7f,sizeof(dis));
memset(vl,0,sizeof(vl));
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
dis[x]=0;
q.push(make_pair(dis[x],x));
while(!q.empty()){
pair<int ,int > t=q.top();q.pop();
if(vl[t.second]) continue;
vl[t.second]=1;
for(int i=head[t.second];i;i=e[i].next){
int v=e[i].v;
int w=e[i].w;
if(dis[v]>dis[t.second]+w) {
dis[v]=dis[t.second]+w;
q.push(make_pair(dis[v],v));
}
}
}
}
int main(){
memset(head,0,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
ad(u,v,w);
ad(v+n,u+n,w);//反向建图
}
dj(1);
for(int i=2;i<=n;++i) ans+=dis[i];
dj(1+n); //反向建图后求到一最短路径
for(int i=2+n;i<=n<<1;++i) ans+=dis[i];
cout<<ans<<endl;
return 0;
}
有疑问评论区留言或私信,欢迎互相交流讨论