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

思路:题目的边权是由随机数给出的,所以最短路径上的边数不会很长,有多条不同走法的最短路的情况出现的概率也很低,所以可以先找出一条最短路,删掉一条边后,转化为 \(k - 1\) 的子问题继续求解,直到 \(k = 0\) ,记录最大值就好。。。。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <cmath>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int maxn = 1e5 + 50;
const LL mod = 1e9 + 7;
int INF = 1e9;
double eps = 1e-6;
int n;
map<pii, int> mp;
struct edge
{
    int to, w, next;
} edge[maxn * 2];

int k, head[maxn];

void add(int a, int b, int c){
    edge[k].to = b;
    edge[k].w = c;
    edge[k].next = head[a];
    head[a] = k++;
}

struct qnode
{
    int u, c;
    bool operator < (const qnode &r) const{
        return c > r.c;
    }
};

priority_queue<qnode> que;
int dis[55][55], vis[maxn], pre[55][55];
int usedge[maxn];
void dj(int id){
    for(int i = 1; i <= n; i++) {
        vis[i] = 0;
        dis[id][i] = INF;
    }
    dis[id][1] = 0;
    que.push({1, 0});
    while(que.size()){
        qnode tmp = que.top();
        que.pop();
        int u = tmp.u;
        if(vis[u]) continue;
        vis[u] = 1;
        for(int i = head[u]; i != -1; i = edge[i].next){
            if(usedge[i]) continue;
            int to = edge[i].to;
            if(vis[to]) continue;
            int w = edge[i].w;
            if(dis[id][to] > dis[id][u] + w){
                dis[id][to] = dis[id][u] + w;
                pre[id][to] = i;
                que.push({to, dis[id][to]});
            }
        }
    } 
}

int ans = 0;
void dfs(int id){
    dj(id);
    if(id == 0){
        ans = max(ans, dis[id][n]);
        return ;
    }
    int node = n;
    while(node != 1){
        usedge[pre[id][node]] = 1;
        dfs(id - 1);
        usedge[pre[id][node]] = 0;
        node = edge[pre[id][node] ^ 1].to;
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        int m;
        ans = 0;
        scanf("%d%d", &n, &m);
        k = 0;
        for(int i = 1; i <= n; i++){
            head[i] = -1;
        }
        for(int i = 1; i <= n * (n - 1) / 2; i++){
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c);
            add(b, a, c);
        }
        dfs(m);
        printf("%d\n", ans);
    }
    return 0;
}
posted @ 2020-07-28 19:47  从小学  阅读(174)  评论(0编辑  收藏  举报