题意:设为
的最短路,
为
的最短路,求
。
数据范围:(SPFA在这个题已经去世了emmm)
注:数据中的边均为单向边。
反向建图的经典应用。
显然,我们可以通过跑从1到其他点的最短路获得。那
怎么求呢,总不能跑n遍Dijk吧。
结论:的最短路等价于在原图的反向边建成的新图中
的最短路。
所以,我们先以1为源点跑一边Dijk,然后在新建的反图上以1为源点跑Dijk。把两者的dis数组相加即为答案。
Code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define ri register int
using namespace std;
const int MAXN=1000020;
const long long INF=(long long)1e18;
int n,m,u[MAXN],v[MAXN],fst[MAXN],nxt[MAXN],infst[MAXN],innxt[MAXN];
long long w[MAXN],dis[MAXN],ans;
bool book[MAXN];
struct node{
int num;
long long c;
};
priority_queue<node>Q;
bool operator<(const node &a,const node &b)
{
return a.c > b.c;
}
void Dijkstra1()
{
for(ri i=1;i<=n;i++) dis[i]=INF;
dis[1]=0; Q.push((node){1,0});
while(!Q.empty())
{
int x=Q.top().num; Q.pop();
if(book[x]) continue;
book[x]=1;
for(ri k=fst[x];k>0;k=nxt[k])
if(dis[v[k]]>dis[u[k]]+w[k])
{
dis[v[k]]=dis[u[k]]+w[k];
Q.push((node){v[k],dis[v[k]]});
}
}
}
void Dijkstra2()
{
for(ri i=1;i<=n;i++) dis[i]=INF;
dis[1]=0; Q.push((node){1,0});
while(!Q.empty())
{
int x=Q.top().num; Q.pop();
if(book[x]) continue;
book[x]=1;
for(ri k=infst[x];k>0;k=innxt[k])
if(dis[u[k]]>dis[v[k]]+w[k])
{
dis[u[k]]=dis[v[k]]+w[k];
Q.push((node){u[k],dis[u[k]]});
}
}
}
inline long long read()
{
long long x=0;
char ch=getchar();
while(ch<'0'||'9'<ch) ch=getchar();
while('0'<=ch&&ch<='9')
{
x=(x <<3)+(x <<1)+(ch-'0');
ch=getchar();
}
return x;
}
int main()
{
n=(int)read(),m=(int)read();
for(ri i=1;i<=m;i++)
{
u[i]=(int)read(),v[i]=(int)read(),w[i]=read();
nxt[i]=fst[u[i]],fst[u[i]]=i;
innxt[i]=infst[v[i]],infst[v[i]]=i;
}
Dijkstra1();
for(ri i=1;i<=n;i++) ans+=dis[i];
memset(book,0,sizeof(book));
Dijkstra2();
for(ri i=1;i<=n;i++) ans+=dis[i];
cout<<ans;
return 0;
}