题目描述
有一个邮递员要送东西,邮局在节点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 的距离,所以直接建反向边就行了。这样只需要跑两次spfa。 代码:
# include <cstdio>
# include <queue>
# include <cstring>
# include <iostream>
# include <vector>
using namespace std;
const int MAXN = 1010;
const int MAXM = 100010;
struct edge{
int t,w,next;
}edges1[MAXM],edges2[MAXM];
int head1[MAXN],head2[MAXN];
int top1,top2;
int dis1[MAXN];
int dis2[MAXN];
bool vis1[MAXN];
bool vis2[MAXN];
typedef pair<int,int> p;
void add1(int f,int t,int w){
edges1[++top1].next = head1[f];
edges1[top1].t = t;
edges1[top1].w = w;
head1[f] = top1;
}
void add2(int f,int t,int w){
edges2[++top2].next = head2[f];
edges2[top2].t = t;
edges2[top2].w = w;
head2[f] = top2;
}
void dijkstra1(){//正图
memset(dis1,0x3f,sizeof(dis1));
memset(vis1,false,sizeof(vis1));
priority_queue<p,vector<p>,greater<p> > q;
dis1[1] = 0;
q.push(make_pair(0,1));
while(!q.empty()){
int top = q.top().second;
q.pop();
if(vis1[top])continue;
vis1[top] = true;
for(int i = head1[top];i!=0;i = edges1[i].next){
int t = edges1[i].t;
if(dis1[t]>dis1[top]+edges1[i].w){
dis1[t]=dis1[top]+edges1[i].w;
q.push(make_pair(dis1[t],t));
}
}
}
}
void dijkstra2(){//反图
memset(dis2,0x3f,sizeof(dis2));
memset(vis2,false,sizeof(vis2));
priority_queue<p,vector<p>,greater<p> > q;
dis2[1] = 0;
q.push(make_pair(0,1));
while(!q.empty()){
int top = q.top().second;
q.pop();
if(vis2[top])continue;
vis2[top] = true;
for(int i = head2[top];i!=0;i = edges2[i].next){
int t = edges2[i].t;
if(dis2[t]>dis2[top]+edges2[i].w){
dis2[t]=dis2[top]+edges2[i].w;
q.push(make_pair(dis2[t],t));
}
}
}
}
int main(void){
int n,m;
cin>>n>>m;
int f,t,w;
for(int i = 1;i<=m;i++){
cin>>f>>t>>w;
add1(f,t,w);
add2(t,f,w);
}
dijkstra1();
dijkstra2();
int ans = 0;
for(int i = 2;i<=n;i++)ans+=dis1[i]+dis2[i];
cout<<ans;
return 0;
}
无脑压行版:
# include <cstdio>
# include <queue>
# include <cstring>
# include <iostream>
# include <vector>
using namespace std;
const int MAXN = 1010;const int MAXM = 100010;struct edge{ int t,w,next; }edges1[MAXM],edges2[MAXM];
int head1[MAXN],head2[MAXN];int top1,top2;int dis1[MAXN];int dis2[MAXN];bool vis1[MAXN];bool vis2[MAXN];typedef pair<int,int> p;
void add1(int f,int t,int w){ edges1[++top1].next = head1[f];edges1[top1].t = t;edges1[top1].w = w;head1[f] = top1; }
void add2(int f,int t,int w){edges2[++top2].next = head2[f];edges2[top2].t = t;edges2[top2].w = w;head2[f] = top2; }
void dijkstra1(){//正图
memset(dis1,0x3f,sizeof(dis1));memset(vis1,false,sizeof(vis1));priority_queue<p,vector<p>,greater<p> > q;dis1[1] = 0;q.push(make_pair(0,1));
while(!q.empty()){
int top = q.top().second;q.pop();if(vis1[top])continue;vis1[top] = true;
for(int i = head1[top];i!=0;i = edges1[i].next){
int t = edges1[i].t;if(dis1[t]>dis1[top]+edges1[i].w)dis1[t]=dis1[top]+edges1[i].w,q.push(make_pair(dis1[t],t));
}
}
}
void dijkstra2(){//反图
memset(dis2,0x3f,sizeof(dis2));memset(vis2,false,sizeof(vis2));priority_queue<p,vector<p>,greater<p> > q;dis2[1] = 0;q.push(make_pair(0,1));
while(!q.empty()){
int top = q.top().second;q.pop();if(vis2[top])continue;vis2[top] = true;
for(int i = head2[top];i!=0;i = edges2[i].next){ int t = edges2[i].t;if(dis2[t]>dis2[top]+edges2[i].w)dis2[t]=dis2[top]+edges2[i].w,q.push(make_pair(dis2[t],t));
}
}
}
int main(void){
int n,m;cin>>n>>m;int f,t,w;
for(int i = 1;i<=m;i++)cin>>f>>t>>w;add1(f,t,w);add2(t,f,w);
dijkstra1();dijkstra2();int ans = 0;for(int i = 2;i<=n;i++)ans+=dis1[i]+dis2[i];cout<<ans;
return 0;
}