ACM/ICPC 之 最短路-SPFA+正逆邻接表(POJ1511(ZOJ2008))

时间:2023-03-08 18:43:51

求单源最短路到其余各点,然后返回源点的总最短路长,以构造邻接表的方法不同分为两种解法。


POJ1511(ZOJ2008)-Invitation Cards

  改变构造邻接表的方法后,分为两种解法

解法一:

 //POJ1511-ZOJ2008
//Time:7766Ms Memory:99112K
//求从1处到各点后再返回1处的最短总路长
//需要构造邻接表和逆邻接表
//构造方法1:vector构造邻接表
//SPFA+邻接表
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std; #define MAX 1000005
#define INF 0x3f3f3f3f struct Edge {
int u, w;
Edge(int uu, int ww) :u(uu), w(ww) {}
}; vector<Edge> e1[MAX], e2[MAX]; //邻接表-逆邻接表 int n, m;
int d[MAX];
long long sum;
bool v[MAX]; void SPFA(int x, vector<Edge> e[MAX])
{
memset(d, INF, sizeof(d));
memset(v, false, sizeof(v));
queue<int> q;
q.push(x);
d[x] = ;
while (!q.empty()){
int cur = q.front();
q.pop();
v[cur] = false;
for (int i = ; i < e[cur].size(); i++)
{
int u = e[cur][i].u;
if (d[u] > d[cur] + e[cur][i].w)
{
d[u] = d[cur] + e[cur][i].w;
if (!v[u]) { q.push(u); v[u] = true; }
}
}
}
for (int i = ; i <= n; i++)
sum += d[i];
} int main()
{
int T;
scanf("%d", &T);
while (T--) {
sum = ;
memset(e1, , sizeof(e1));
memset(e2, , sizeof(e2));
scanf("%d%d", &n, &m);
while (m--) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
e1[u].push_back(Edge(v, w)); //正向
e2[v].push_back(Edge(u, w)); //逆向
} SPFA(, e1);
SPFA(, e2);
printf("%lld\n", sum);
} return ;
}

解法二:

 //POJ1511-ZOJ2008
//Time:2000Ms Memory:36424K
//求从1处到各点后再返回1处的最短总路长
//需要构造邻接表和逆邻接表
//构造方法2:偏序关系构造邻接表
//SPFA+邻接表
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std; #define MAX 1000005
#define INF 0x3f3f3f3f struct Edge {
int u, w, next;
Edge() {}
Edge(int uu, int ww, int nn) :u(uu), w(ww), next(nn) {}
}e1[MAX], e2[MAX]; //邻接表-逆邻接表 int h1[MAX], h2[MAX]; //正表表头-逆表表头
int n, m;
int d[MAX];
long long sum;
bool v[MAX]; void SPFA(int x, Edge e[MAX], int h[MAX])
{
memset(d, INF, sizeof(d));
memset(v, false, sizeof(v));
queue<int> q;
q.push(x);
d[x] = ;
while (!q.empty()){
int cur = q.front();
q.pop();
v[cur] = false;
for (int i = h[cur]; i != -; i = e[i].next)
{
int u = e[i].u;
int w = e[i].w;
if (d[u] > d[cur] + w)
{
d[u] = d[cur] + w;
if (!v[u]) { q.push(u); v[u] = true; }
}
}
}
for (int i = ; i <= n; i++)
sum += d[i];
} int main()
{
int T;
scanf("%d", &T);
while (T--) {
sum = ;
memset(e1, , sizeof(e1));
memset(e2, , sizeof(e2));
memset(h1, -, sizeof(h1));
memset(h2, -, sizeof(h2));
scanf("%d%d", &n, &m);
for (int i = ; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
e1[i] = Edge(v, w, h1[u]);
e2[i] = Edge(u, w, h2[v]);
h1[u] = h2[v] = i;
} SPFA(, e1, h1);
SPFA(, e2, h2);
printf("%lld\n", sum);
} return ;
}