题目
思路
题目的k很小,最大为5。
图的点数也很小,最多50。
由于题目的边权是随机生成的,所以用spfa跑最短路,所获得的最短路径不会太长。(随机生成,出题人没有想卡spfa)
那就每次都跑一次最短路,记录路径,枚举删除这个路径上的每一条边,继续在删了边后的图上跑最短路,直到删了k条边,这时候直接跑一个最短路的距离。取最大值即可。
由于n k很小,并且没有卡spfa,时间复杂度不会到达50^5。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100;
const int INF = 0x3f3f3f3f3f;
int f[maxn][maxn];
int dis[maxn];//最短距离
int from[maxn];//路径还原
bool con[maxn][maxn];//connect 标记i 与j是否相连
bool in[maxn];//spfa
int n, k, ans;
void spfa(){
queue <int> q;
for(int i = 2 ; i <= n; i++)
dis[i] = INF;
dis[1] = 0; in[1] = true; q.push(1);
int u, v;
while(!q.empty()){
u = q.front(); q.pop();
for(v = 1; v <= n; v++){
if(con[u][v] && dis[v] > dis[u] + f[u][v]){
dis[v] = dis[u] + f[u][v];
from[v] = u;
if(!in[v]){
in[v] = true;
q.push(v);
}
}
}
in[u] = false;
}
}
void solve(int now){
if(now > k){
spfa();
ans = max(ans, dis[n]);
return;
}
spfa();
int u = n, len = 1;
vector <int> r;
r.push_back(n);
while(u != 1){
u = from[u];
++len;
r.push_back(u);
}
for(int i = 0; i < len - 1; i++){
con[r[i]][r[i + 1]] = con[r[i + 1]][r[i]] = false;
solve(now + 1);
con[r[i]][r[i + 1]] = con[r[i + 1]][r[i]] = true;
}
}
int main(){
int t; scanf("%d", &t);
while(t--){
scanf("%d %d", &n, &k);
for(int i = 1, u, v, w; i <= n * (n - 1) / 2; i++){
scanf("%d %d %d", &u, &v, &w);
f[u][v] = f[v][u] = w;
con[u][v] = con[v][u] = true;
}
ans = 0;
solve(1);
printf("%d\n", ans);
}
return 0;
}