题目链接:kuangbin带你飞 专题四 最短路练习 J - Invitation Cards
题意
求源点到各点的往返最短路之和
思路
本体思路没什么难度,分别用正反图求两次单源最短路即可,邻接表不好逆置,直接在最初构建两个图即可。
数据量相当大,timeout了两次,第一次是直接spfa,第二次用vector做邻接表仍然超时,第三次自己构建邻接表算是过了
代码
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1000009;
const int MAX = 0x3f3f3f3f;
bool vis[N];
long long d[N];
long long ans[N] = {};
int head1[N], head2[N];
struct Edge
{
int u, v, w, next;
}e1[N], e2[N];
void spfa(int n, Edge e[], int head[])
{
memset(vis, 0, sizeof(vis));
for(int i=1; i<=n; i++)
d[i] = MAX;
d[1] = 0;
vis[1] = 1;
queue<int> q;
q.push(1);
while(!q.empty())
{
int x = q.front();
q.pop();
vis[x] = 0;
for(int i=head[x]; i!=-1; i=e[i].next)
{
if(d[e[i].v] > d[x] + e[i].w)
{
d[e[i].v] = d[x] + e[i].w;
if(!vis[e[i].v])
{
q.push(e[i].v);
vis[e[i].v] = 1;
}
}
}
}
for(int i=1; i<=n; i++)
ans[i] += d[i];
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
scanf("%d%d", &n, &m);
memset(ans, 0, sizeof(ans));
memset(head1, -1, sizeof(head1));
memset(head2, -1, sizeof(head2));
for(int i=0; i<m; i++)
{
scanf("%d%d%d", &e1[i].u, &e1[i].v, &e1[i].w);
e1[i].next = head1[e1[i].u];
head1[e1[i].u] = i;
e2[i].u = e1[i].v;
e2[i].v = e1[i].u;
e2[i].w = e1[i].w;
e2[i].next = head2[e2[i].u];
head2[e2[i].u] = i;
}
spfa(n, e1, head1);
spfa(n, e2, head2);
long long rel = 0;
for(int i=1; i<=n; i++)
rel += ans[i];
printf("%lld\n", rel);
}
return 0;
}