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