先跑一遍floyed,求出两两点对之间的最小距离。然后这个最小距离就相当于一个最新的地图了,新地图里,小于当前二分枚举值,就充1次电,大于这个值,就冲无穷大次电,起点终点相等,就充0次电。再跑一次floyed,看看当前二分枚举的容量符不符合条件。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
const long long inf = 0x3f3f3f3f3f3f3f3f3f3f3f;
long long a[110][110],mapp[110][110];
int t,n,k,m;
int main()
{
scanf("%d",&t);
while (t--)
{
scanf("%d%d%d",&n,&k,&m);
memset(mapp,inf,sizeof(mapp));
for (int i=1; i<=m; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
mapp[a][b]=mapp[b][a]=c;
}
for (int k=0; k<n; k++)
{
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
{
mapp[i][j]=min(mapp[i][j],mapp[i][k]+mapp[k][j]);
}
}
}
long long l=1; long long r=inf; long long mid; long long ans;
while (l<=r)
{
mid=l+r>>1;
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
{
if (i==j) a[i][j]=0;
else if (mapp[i][j]<=mid) a[i][j]=1;
else a[i][j]=inf;
}
}
for (int k=0; k<n; k++)
{
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
{
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
}
}
}
bool flag=true;
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
{
if (a[i][j]>k)
{
flag=false;
break;
}
}
if (!flag) break;
}
if (flag)
{
r=mid-1; ans=mid;
}
else l=mid+1;
}
cout<<ans<<endl;
}
return 0;
}