一句话题意:喊你求出从1出发到所有点的最短路以及所有点的最短路到1的最短路之和。
从1开始跑最短路很容易,直接一遍堆优化dijkstra就完了。
对于其他点到1的最短路又怎么求,不可能一个一个的求,所以想到之前暑假讲关于图论的技巧——建反图。
这样的话问题就迎刃而解了,再在反图上从1开始跑一遍最短路就完了。
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+7;
const int inf=0x7fffffff;
struct node1{
int nxt,to,val;
}edge1[maxn*3];
struct node2{
int nxt,to,val;
}edge2[maxn*3];
priority_queue<pair<long long ,int > >q1;
priority_queue<pair<long long ,int > >q2;
long long dis1[maxn],dis2[maxn];
int cnt1,cnt2;
int n,m;
int x,y,v;
int head1[maxn],head2[maxn];
void add1(int x,int y,int v){
edge1[++cnt1].nxt=head1[x];
edge1[cnt1].to=y;
edge1[cnt1].val=v;
head1[x]=cnt1;
}
void add2(int x,int y,int v){
edge2[++cnt2].nxt=head2[x];
edge2[cnt2].to=y;
edge2[cnt2].val=v;
head2[x]=cnt2;
}
bool vis1[maxn];
long long ans1;
void dijkstra1(int x){
for(int i=1;i<=n;i++){
dis1[i]=inf;
vis1[i]=false;
}
dis1[x]=0;
q1.push(make_pair(0,x));
while(q1.size()){
int u=q1.top().second;
q1.pop();
if(vis1[u]) continue;
vis1[u]=true;
for(int i=head1[u];i;i=edge1[i].nxt){
int v=edge1[i].to;
if(dis1[v]>dis1[u]+edge1[i].val){
dis1[v]=dis1[u]+edge1[i].val;
q1.push(make_pair(-dis1[v],v));
}
}
}
for(int i=1;i<=n;i++) ans1+=dis1[i];
}
long long ans2;
bool vis2[maxn];
void dijkstra2(int x){
for(int i=1;i<=n;i++){
vis2[i]=false;
dis2[i]=inf;
}
dis2[x]=0;
q2.push(make_pair(0,x));
while(q2.size()!=0){
int u=q2.top().second;
q2.pop();
if(vis2[u]) continue;
for(int i=head2[u];i;i=edge2[i].nxt){
int v=edge2[i].to;
if(dis2[v]>dis2[u]+edge2[i].val){
dis2[v]=dis2[u]+edge2[i].val;
q2.push(make_pair(-dis2[v],v));
}
}
}
for(int i=1;i<=n;i++) ans2+=dis2[i];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&v);
add1(x,y,v);
add2(y,x,v);
}
dijkstra1(1);
dijkstra2(1);
long long final=ans1+ans2;
printf("%lld\n",final);
return 0;
}
