UVALive - 4080 Warfare And Logistics (SPFA+最短路树)

来源:互联网 发布:简述网络贷款的危害 编辑:程序博客网 时间:2024/05/16 04:08

题目大意:有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 0x3f3f3f3fstruct 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;}
0 0