2020 杭电多校第三场 1007 Tokitsukaze and Rescue(spfa)

题目

题目链接

思路

题目的k很小,最大为5。
图的点数也很小,最多50。
由于题目的边权是随机生成的,所以用spfa跑最短路,所获得的最短路径不会太长。(随机生成,出题人没有想卡spfa)
那就每次都跑一次最短路,记录路径,枚举删除这个路径上的每一条边,继续在删了边后的图上跑最短路,直到删了k条边,这时候直接跑一个最短路的距离。取最大值即可。
由于n k很小,并且没有卡spfa,时间复杂度不会到达50^5。
在这里插入图片描述

代码

#include 
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;
}

参考来源

博客题解

你可能感兴趣的:(图论,基础图论)