题目大意:有N个点,M条边,每次删掉一条边,问删掉该边后,所有点之间的最短路的和是多少

解题思路:刚开始就想,删掉一次floyd一次,结果可想而之,TLE了
后来看了别人的,发现了一种叫做最短路树的东西。
就是先求出以每个点为源点的最短路并纪录该点到每个点的距离和,和每个点的pre,这样的话,就预处理好了
因为要删掉边,前面我们已经预处理好了最短路树的pre,也就是说,就可以依次判断删除的边是否在最短路树上,只要你要删除的边不在该最短路树上,那么就没有影响了,可以直接用前面纪录的数据
如果要删掉的边有影响的话,那就将该边标记下,再跑一次最短路,求出最优解即可

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define N 110
#define M 6020
#define INF 0x3f3f3f3f

struct Edgs{
    int to, next;
}E[M];

struct Node {
    int x, y;
}node[M];

int d[N], pre[N][N], num[N][N], sum[N], head[N];
int cnt, n, m;
bool flag = true;
bool vis[N];

void add_edgs(int u, int v) {
    E[cnt].to = v;
    E[cnt].next = head[u];
    head[u] = cnt++;
}

void init(){ 
    memset(num, 0, sizeof(num));
    memset(head, -1, sizeof(head));
    cnt = 0;
    int x, y;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &x, &y);
        node[i].x = x;    node[i].y = y;
        num[x][y]++;      num[y][x]++;
        add_edgs(x, y);   add_edgs(y, x);   
    }
}

void bfs(int s) {
    queue<int> q;
    for (int i = 1; i <= n; i++) {
        d[i] = INF;
        vis[i] = false;
    }
    d[s] = 0;
    pre[s][s] = 0;
    vis[s] = 1;
    q.push(s);

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (int i = head[u]; i != -1; i = E[i].next) {
            int v = E[i].to;
            if (!vis[v]) {
                d[v] = d[u] + 1;
                vis[v] = 1;
                pre[s][v] = u;
                q.push(v);
            }
        }
    }
    sum[s] = 0;
    for (int i = 1; i <= n; i++) {
        if (d[i] == INF) {
            flag = false;
            return ;
        }
        sum[s] += d[i];
    }
}

int bfs2(int s) {
    queue<int> q;
    for (int i = 1; i <= n; i++) {
        vis[i] = false;
        d[i] = INF;
    }
    d[s] = 0;
    vis[s] = true;  
    q.push(s);

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (int i = head[u]; i != -1; i = E[i].next) {
            int v = E[i].to;
            if (num[u][v] && !vis[v]) {
                d[v] = d[u] + 1;
                vis[v] = true;
                q.push(v);
            }
        }
    }

    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (d[i] == INF)
            return -1;
        ans += d[i];
    }
    return ans;
}

void solve() {

    flag = true;
    for (int i = 1; i <= n; i++) {
        if (flag) 
            bfs(i);
        else
            break;
    }

    for (int i = 0; i < m; i++) {

        if (!flag) {
            printf("INF\n");
            continue;
        }
        int x = node[i].x;
        int y = node[i].y;

        int ans = 0, j;
        for (j = 1; j <= n; j++) {
            if (pre[j][x] != y && pre[j][y] != x) {
                ans += sum[j];
                continue;
            }
            num[x][y]--; num[y][x]--;

            int t = bfs2(j);

            num[y][x]++; num[x][y]++;

            if (t == -1) {
                printf("INF\n");
                break;
            }
            ans += t;
        }
        if (j == n + 1)
            printf("%d\n", ans);
    }
}

int main() {
    while (scanf("%d%d", &n, &m) != EOF) {
        init();
        solve();
    }
    return 0;
}