题目链接
题解
题意
找到任意两点的最短路,求和。
思路
- Floyd 看一下数据范围,超时警告(在不使用奇技淫巧的情况下)。
- 别的没尝试,数据范围比较大,稳妥一点使用了Dij。建立反向图,正向一遍反向一遍,求和就好。
AC代码
#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(A, tree) memcpy(A, tree, sizeof(tree))
#define eps (1e-8)
#define PI (acos(-1.0))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;
inline int read() {
char a = 0;
int x = 0, w = 1;
while (a < '0' || a > '9') {
if (a == '-')w = -1;
a = getchar();
}
while (a >= '0' && a <= '9') {
x = (x << 3) + (x << 1) + (a ^ 48);
a = getchar();
}
return x * w;
}
const int N = 1e3 + 10, M = 1e5 + 10;
struct E {
int to, ne, w;
} e[M], fe[M];
int head[M], cnt = 1;
int fhead[M], fcnt = 1;
void add(int u, int v, int w) {
e[cnt].w = w;
e[cnt].ne = head[u];
e[cnt].to = v;
head[u] = cnt++;
}
void fadd(int u, int v, int w) {
fe[fcnt].w = w;
fe[fcnt].ne = fhead[u];
fe[fcnt].to = v;
fhead[u] = fcnt++;
}
int d[N], fd[N];
int n, m;
int vis[N], fvis[N];
void dij() {
for (int i = 1; i <= n; i++) {
d[i] = INF;
}
d[1] = 0;
while (true) {
int u = -1;
for (int i = 1; i <= n; i++) {
if (!vis[i] && (u == -1 || d[i] < d[u])) u = i;
}
if (u == -1) break;
vis[u] = 1;
for (int i = head[u]; i; i = e[i].ne) {
int v = e[i].to, w = e[i].w;
if (d[v] > d[u] + w) {
d[v] = d[u] + w;
}
}
}
}
void fdij() {
for (int i = 1; i <= n; i++) {
fd[i] = INF;
}
fd[1] = 0;
while (true) {
int u = -1;
for (int i = 1; i <= n; i++) {
if (!fvis[i] && (u == -1 || fd[i] < fd[u])) u = i;
}
if (u == -1) break;
fvis[u] = 1;
for (int i = fhead[u]; i; i = fe[i].ne) {
int v = fe[i].to, w = fe[i].w;
if (fd[v] > fd[u] + w) {
fd[v] = fd[u] + w;
}
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
mms(head, 0);
mms(fhead, 0);
n = read();
m = read();
for (int i = 1; i <= m; i++) {
int u, v, w;
u = read();
v = read();
w = read();
add(u, v, w);
fadd(v, u, w);
}
dij();
fdij();
int sum = 0;
for (int i = 2; i <= n; i++) {
sum += d[i] + fd[i];
}
printf("%d", sum);
return 0;
}
后记
这个题真的。。让我有些迷惑。
刚开始用的是堆优化的dij,然后会一直在最后一个测试用例tle,这就很迷惑了。。如果有大佬的话还请赐教呀。
TLE代码
#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(A, tree) memcpy(A, tree, sizeof(tree))
#define eps (1e-8)
#define PI (acos(-1.0))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;
inline int qr()
{
char a=0;int x=0,w=1;
while(a<'0'||a>'9'){if(a=='-')w=-1;a=getchar();}
while(a>='0'&&a<='9'){x=(x<<3)+(x<<1)+(a^48);a=getchar();}
return x*w;
}
const int N = 1e3 + 10, M = 1e5 + 10;
struct E {
int to, ne, w;
} e[M], fe[M];
int head[M], cnt = 1;
int fhead[M], fcnt = 1;
void add(int u, int v, int w) {
e[cnt].w = w;
e[cnt].ne = head[u];
e[cnt].to = v;
head[u] = cnt++;
}
void fadd(int u, int v, int w) {
fe[fcnt].w = w;
fe[fcnt].ne = fhead[u];
fe[fcnt].to = v;
fhead[u] = fcnt++;
}
int d[N], fd[N];
int n, m;
void dij() {
for (int i = 1; i <= n; i++) {
d[i] = INF;
}
priority_queue<P> q;
q.push(P(0, 1));
d[1] = 0;
while (!q.empty()) {
int x = q.top().second, di = q.top().first;
q.pop();
if (di > d[x]) continue;
for (int j = head[x]; j; j = e[j].ne) {
int i = e[j].to;
if (d[i] > e[j].w + d[x]) {
d[i] = e[j].w + d[x];
q.push(P(d[i], i));
}
}
}
}
void fdij() {
for (int i = 1; i <= n; i++) {
fd[i] = INF;
}
priority_queue<P> q;
q.push(P(0, 1));
fd[1] = 0;
while (!q.empty()) {
int x = q.top().second, di = q.top().first;
q.pop();
if (di > fd[x]) continue;
for (int j = fhead[x]; j; j = fe[j].ne) {
int i = fe[j].to;
if (fd[i] > fe[j].w + fd[x]) {
fd[i] = fe[j].w + fd[x];
q.push(P(fd[i], i));
}
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
mms(head, 0);
mms(fhead, 0);
n = qr(); m = qr();
for (int i = 1; i <= m; i++) {
int u, v, w;
u = qr();v = qr(); w = qr();
add(u, v, w);
fadd(v, u, w);
}
dij();
fdij();
int sum = 0;
for (int i = 2; i <= n; i++) {
sum += d[i] + fd[i];
}
printf("%d", sum);
return 0;
}