题目大意:
求1号点到各个点的最短距离,以及各个点到1号点的最短距离。
思路:
链式前向星+dijkstra堆优化
正反向存图+2次dijkstra
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1000010;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to, dis, next;
};
Edge e[N << 1];
int head[N], dis[N], cnt;
Edge re[N << 1];
int rhead[N], rdis[N], rcnt;
bool vis[N];
int n, m, s;
LL ans;
void init() {
ans = 0;
s = 1;
memset(head, -1, sizeof(head));
memset(rhead, -1, sizeof(rhead));
for (int i = 1; i <= n; i++)
dis[i] = rdis[i] = INF;
cnt = rcnt = 0;
}
void add_Edge(int u, int v, int d)
{
e[++cnt].dis = d;
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void radd_Edge(int u, int v, int d)
{
re[++rcnt].dis = d;
re[rcnt].to = v;
re[rcnt].next = rhead[u];
rhead[u] = rcnt;
}
struct node
{
int dis, pos;
bool operator<(const node &x) const
{
return x.dis < dis;
}
};
void dijkstra()
{
memset(vis, 0, sizeof(vis));
priority_queue<node> q;
dis[s] = 0;
q.push({0, s});
while (!q.empty())
{
node tmp = q.top();
q.pop();
int x = tmp.pos;
if (vis[x])
continue;
vis[x] = 1;
for (int i = head[x]; ~i; i = e[i].next)
{
int y = e[i].to;
if (dis[y] > dis[x] + e[i].dis)
{
dis[y] = dis[x] + e[i].dis;
if (!vis[y])
q.push({dis[y], y});
}
}
}
for (int i = 1; i <= n; i++) ans += dis[i];
}
void rdijkstra()
{
memset(vis, 0, sizeof(vis));
priority_queue<node> q;
rdis[s] = 0;
q.push({0, s});
while (!q.empty())
{
node tmp = q.top();
q.pop();
int x = tmp.pos;
if (vis[x])
continue;
vis[x] = 1;
for (int i = rhead[x]; ~i; i = re[i].next)
{
int y = re[i].to;
if (rdis[y] > rdis[x] + re[i].dis)
{
rdis[y] = rdis[x] + re[i].dis;
if (!vis[y])
q.push({rdis[y], y});
}
}
}
for (int i = 1; i <= n; i++) ans += rdis[i];
}
signed main()
{
int T; scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &m);
init();
for (int i = 0; i < m; i++)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
add_Edge(u, v, w);
radd_Edge(v, u, w);
}
dijkstra();
rdijkstra();
printf("%lld
", ans);
}
return 0;
}