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 kk
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 kk
(3≤n≤50,1≤k≤min(n−2,5))(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\times (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≤\(10^4\)), 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 \(10^4\).
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条边,使得新图的最短路尽可能大。
看到数据范围应该想到暴力的QAQ。如果当前图中最短路已经求出来了,且需要删除k条边,要删边的话肯定从最短路的边里删(要不然删不删没区别),然后枚举这条最短路的每条边选择删除,进行递归(子问题为需要删除k-1条边..)。等删掉k条边后再跑一次最短路,用d[n]更新答案。
需要注意的问题:
1)注意到为完全图且n很小,可以直接跑\(O(n^2)\)的Dijkstra。
2)“边权随机的情况下,最短路的边数很少。”整体复杂度 \(O(n^2 \times c^k)\),c 为最短路边数。
3)注意路径记录。松弛的时候path[y] = x;枚举边的时候从n~1倒着枚举,用bool cut[55][55]标记砍哪条边,记得回溯。
#include
using namespace std;
int a[55][55], d[55], path[55], n, k, ans;
bool v[55];
bool cut[55][55];//标记哪条边被暂时删除了
void dijkstra()
{
memset(d, 0x3f3f3f3f, sizeof(d));
memset(v, 0, sizeof(v));
memset(path, 0, sizeof(path));
d[1] = 0;
path[1] = 0;
for(int i = 1; i < n; i++)
{
int x = 0;
for(int j = 1; j <= n; j++)
{
if(!v[j] && (x == 0 || d[j] < d[x])) x = j;
}
v[x] = 1;
for(int y = 1; y <= n; y++)
{
if(d[x] + a[x][y] < d[y] && !cut[x][y])
{
d[y] = d[x] + a[x][y];
path[y] = x;
}
}
}
}
void dfs(int x)
{
dijkstra();
if(x == k + 1)//删k条边要跑k+1次dij,最后一次求答案
{
ans = max(ans, d[n]);
return;
}
for(int i = n, pre = n; i; i = path[i])
{
cut[i][pre] = cut[pre][i] = 1;
dfs(x + 1);
cut[i][pre] = cut[pre][i] = 0;
pre = i;
}
}
int main()
{
//freopen("1007.in","r",stdin);
//freopen("my.out","w",stdout);
int t;
cin >> t;
while(t--)
{
cin >> n >> k;
memset(a, 0x3f3f3f3f, sizeof(a));
memset(cut, 0, sizeof(cut));//貌似不写也没事?
ans = -0x3f3f3f3f;
for(int i = 1; i <= n; i++) a[i][i] = 0;
for(int i = 1; i <= n * (n - 1) / 2; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
a[u][v] = a[v][u] = w;
}
dfs(1);
cout << ans << endl;
}
return 0;
}