题目大意:有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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-25 00:59:39