题目大意:有N个点,M条路,如果两条路不连通的话,就将这两条路的距离设置为L
现在要求你求出每两点之间的最短距离和
接着要求
求出炸断 给出的M条路中的一条路后,每两点之间的最短距离和的最大值
解题思路:这题跟HDU-2433类似,不过这题的权值是不一样的
但具体的思路是差不多的
先预处理出以每个点为源点的最短路树,并纪录每个点的pre和以每个点为源点的最短距离和,这样就可以求出每两点之间的最短距离和了
接着依次删边,如果删除的边不在该点最短路树上,那么就可以用预处理纪录的以该点为源点的最短距离和了
如果在最短路树上,就记录一下删除的边,再跑一遍以该点为源点的最短路即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define N 110
#define M 15010
#define INF 0x3f3f3f3f
struct Edge {
int to, next, dist;
}E[M];
struct Node {
int x, y, id;
}node[M];
int n, m, l, tot;
int head[N], pre[N][N], Sum[N], d[N];
bool vis[N];
void AddEdge(int u, int v, int dist) {
E[tot].to = v;
E[tot].dist = dist;
E[tot].next = head[u];
head[u] = tot++;
}
void init() {
memset(head, -1, sizeof(head));
tot = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (i != j)
AddEdge(i, j, l);
}
int u, v, d;
for (int i = 0; i < m; i++){
scanf("%d%d%d", &u, &v, &d);
node[i].x = u;
node[i].y = v;
node[i].id = tot;
AddEdge(u, v, d);
AddEdge(v, u, d);
}
}
void SPFA1(int s) {
for (int i = 1; i <= n; i++) {
d[i] = INF;
vis[i] = false;
}
queue<int> q;
q.push(s);
d[s] = 0;
pre[s][s] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head[u]; i != -1; i = E[i].next) {
int v = E[i].to;
if (d[v] > d[u] + E[i].dist) {
d[v] = d[u] + E[i].dist;
pre[s][v] = u;
if (!vis[v]) {
vis[v] = true;
q.push(v);
}
}
}
}
for (int i = 1; i <= n; i++)
Sum[s] += d[i];
}
int SPFA2(int s, int id) {
for (int i = 1; i <= n; i++) {
d[i] = INF;
vis[i] =false;
}
d[s] = 0;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head[u]; i != -1; i = E[i].next) {
if (i == id || i == id + 1)
continue;
int v = E[i].to;
if (d[v] > d[u] + E[i].dist) {
d[v] = d[u] + E[i].dist;
if (!vis[v]) {
q.push(v);
vis[v] = true;
}
}
}
}
int S = 0;
for (int i = 1; i <= n; i++)
S += d[i];
return S;
}
void solve() {
int S = 0;
for (int i = 1; i <= n; i++) {
Sum[i] = 0;
SPFA1(i);
S += Sum[i];
}
int Max = -INF;
for (int i = 0; i < m; i++) {
int t = 0;
int x = node[i].x, y = node[i].y, id = node[i].id;
for (int j = 1; j <= n; j++) {
if (pre[j][x] != y && pre[j][y] != x) {
t += Sum[j];
continue;
}
t += SPFA2(j, id);
}
Max = max(Max, t);
}
printf("%d %d\n", S, Max);
}
int main() {
while (scanf("%d%d%d", &n, &m, &l) != EOF) {
init();
solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-09 17:15:53