2020杭電多校第三場 1007 Tokitsukaze and Rescue
阿新 • • 發佈:2020-07-28
思路:題目的邊權是由隨機數給出的,所以最短路徑上的邊數不會很長,有多條不同走法的最短路的情況出現的概率也很低,所以可以先找出一條最短路,刪掉一條邊後,轉化為 \(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; }