2020杭电多校第三场 Tokitsukaze and Rescue(最短路,随机数据)

Problem Description
Princess CJB has lived almost her entire life in the isolated town of Ertona, where CJB uses her unique ability to recognize where crystals of materials are buried. By way of a fateful encounter, CJB learns of the Alchemy Exam and decides to take her first step into the outside world, setting off on a grand journey to become a certified alchemist and discover the mysteries that life has to offer!

In order to take part in the Alchemy Exam, CJB goes to the Reisenberg town without any partners. But the kingdom Adalet is unbelievably enormous so that there are many hidden risks. Claris, a powerful evil magician, wants to monopolize CJB for the extraordinary beauty of her. Due to the power limitation of CJB, she can’t escape from Claris without any assistance. The alchemist Tokitsukaze has heard this savage act and wants to rescue the princess CJB.

There are n cities numbered from 1 to n in the kingdom Adalet. Because of the excellent transportation, there is exactly a two-way road between any two cites. Tokitsukaze lives in city 1. The Magician Claris lives in city n. Since the exam will be held soon, Tokitsukaze wants to rescue CJB as fast as possible, so she will choose the shortest path to reach city n.

Claris has also heard this news and is afraid of being punished, so he decides to slow Tokitsukaze down by making an explosion on k roads he chose and causing these roads to lose their capability of two-way transportation, since it can pave the way for having enough time to prepare his powerful magic against Tokitsukaze.

Tokitsukaze knows some roads will be destroyed and can immediately recognize where they are, but she has no approach to prevent this explosion, so she chooses just to move along the shortest path after Claris completes his explosion.

Now Claris wants to know, after finishing his explosion, what the longest possible length is of the shortest path from city 1 to city n.

Input
There are several test cases.

The first line contains an integer T (1≤T≤100), denoting the number of test cases. Then follow all the test cases.

For each test case, the first line contains two integers n and k (3≤n≤50,1≤k≤min(n−2,5)), denoting the number of cities and the number of roads being exploded, respectively.

The next n(n−1)2 lines describe all the roads, where each line contains three integers u, v and w (1≤u,v≤n,u≠v,1≤w≤104), representing a two-way road of length w between city u and city v. It is guaranteed that for every two cities, there exists exactly one road whose length is randomly distributed between 1 and 104.

Output
For each case, output in one line an integer, denoting the longest possible length of the shortest path after the explosion.

Sample Input
3
5 1
1 2 2990
1 3 2414
1 4 4018
1 5 6216
2 3 9140
2 4 4169
2 5 550
3 4 6618
3 5 3206
4 5 105
5 2
1 2 2990
1 3 2414
1 4 4018
1 5 6216
2 3 9140
2 4 4169
2 5 550
3 4 6618
3 5 3206
4 5 105
5 3
1 2 2990
1 3 2414
1 4 4018
1 5 6216
2 3 9140
2 4 4169
2 5 550
3 4 6618
3 5 3206
4 5 105

Sample Output
4123
5620
6216

题意:
完全图。问删除 k k k条边最短路的最大值。保证数据随机

思路:
很虚假的一道题啊。
因为数据随机,所以最短路边数很少。并且 k k k很小,所以可以枚举删除当前最短路哪条边,然后再跑最短路再枚举删除这条边,递归下去。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <queue>

using namespace std;

typedef long long ll;

const int maxn = 1e3 + 7;
const int INF = 0x3f3f3f3f;
int a[55][55],d[55],vis[55];
int vis2[maxn][maxn];
int pre[55],ans;
int n,k;

int dijkstra() {
    priority_queue<pair<int,int> >q;
    memset(d,0x3f,sizeof(d));
    memset(vis,0,sizeof(vis));
    memset(pre,0,sizeof(pre));
    q.push({0,1});
    d[1] = 0;
    while(!q.empty()) {
        int now = q.top().second;q.pop();
        if(vis[now]) continue;
        vis[now] = 1;
        for(int i = 1;i <= n;i++) {
            if(vis2[now][i]) continue;
            if(i == now) continue;
            if(d[i] > d[now] + a[i][now]) {
                d[i] = d[now] + a[i][now];
                pre[i] = now;
                q.push({-d[i],i});
            }
        }
    }
    return d[n];
}

void dfs(int cnt) { //删了多少条边
    if(cnt == k) {
        ans = max(ans,dijkstra());
        return;
    }
    dijkstra();
    
    vector<pair<int,int> >edges;
    int now = n;
    
    while(pre[now]) {
        edges.push_back({pre[now],now});
        now = pre[now];
    }
    
    for(int i = 0;i < edges.size();i++) {
        int x = edges[i].first,y = edges[i].second;
        vis2[x][y] = 1;
        vis2[y][x] = 1;
        dfs(cnt + 1);
        vis2[x][y] = 0;
        vis2[y][x] = 0;
    }
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n;i++) {
            for(int j = i + 1;j <= n;j++) {
                int x,y,z;scanf("%d%d%d",&x,&y,&z);
                a[x][y] = a[y][x] = z;
            }
        }
        
        ans = 0;

        dfs(0);
        printf("%d\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值