题意:
给你一张n个节点的完全图, 去掉k条边使图的最短路最大,求这个最大值。
思路:
边权随机的情况下,最短路的边数很少。
所以只要每次跑一下最短路,抓一条最短路出来,枚举删除最短路上的哪条边,然后递归,变成删 除 (k−1) 条边的子问题。 重复这过程直到 k = 0,然后再跑一次 1 到 n 最短路,把结果取 max 即可。 复杂度 O(n2 ∗ck),c 为最短路边数
题意:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 55;
const int inf = 1 << 30;
int mp[maxn][maxn], d[maxn], pre[10][maxn], ans;
bool vis[maxn];
int n, k;
void dfs(int m){
for(int i = 1; i <= n; i++) d[i] = inf, vis[i] = false; //跑最短路
d[1] = 0;
for(int i = 1; i <= n; i++){
int u = -1;
for(int j = 1; j <= n; j++)
if(!vis[j]) if(u == -1 || d[u] > d[j]) u = j;
vis[u] = true;
if(vis[n]) break;
for(int j = 1; j <= n; j++){
if(!vis[j] && d[u] + mp[u][j] < d[j]){
d[j] = d[u] + mp[u][j];
pre[m][j] = u;
}
}
}
if(!m) {
ans = max(ans, d[n]);
return;
}
int i, j = -1, h;
for(i = n; j != 1; i = j){ //枚举去掉当前最短路的边,往下dfs
j = pre[m][i];
h = mp[i][j];
mp[i][j] = mp[j][i] = inf;
dfs(m - 1);
mp[i][j] = mp[j][i] = h;
}
}
int main(){
int t, u, v, w;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
for(int i = 0; i < (n - 1) * n / 2; i++){
scanf("%d%d%d", &u, &v, &w);
mp[u][v] = mp[v][u] = w;
}
ans = 0;
dfs(k);
printf("%d\n", ans);
}
}