简单猜测构成最短路的边不会很多。(因为每条边的边范围权一样的,所以如果要构造一条比当前最短路的边多还要短的路径的话对每条边的边权限制就要比之前更严格……虽然具体概率不会算就是了)
这个思路比赛的时候就想到了,一直在想每次删掉最短路中的那条边最优,结果是个爆搜。而且我比赛的时候竟然没看了一下时间限制,以后一定要记住。
题目中的边权随机很重要,我看题的时候自动忽略了。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int mp[100][100];
int dis[100];
int vis[100];
int f[100][100];
int n,k;
int ans=0;
void dfs(int cnt)
{
memset(vis,0,sizeof vis);
memset(dis,0x3f,sizeof dis);
dis[1]=0;
for(int i=1;i<n;i++)
{
int x=0;
for(int j=1;j<=n;j++)
{
if(vis[j]==0&&(x==0||dis[x]>dis[j]))
{
x=j;
}
}
vis[x]=1;
for(int j=1;j<=n;j++)
{
if(mp[x][j]!=-1&&dis[j]>dis[x]+mp[x][j])
{
dis[j]=dis[x]+mp[x][j];
f[cnt][j]=x;//记录最短路路径。记录每个点是从哪个点转移过来的。
}
}
}
if(cnt==0)
{
if(ans<dis[n]) ans=dis[n];
return;
}
int j;
for(int i=n;i!=1;i=j)//循环中要用到的数组和变量一定要恢复,或者直接多开一维。
{
j=f[cnt][i];
int num=mp[i][j];
mp[i][j]=mp[j][i]=-1;
dfs(cnt-1);
mp[i][j]=mp[j][i]=num;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans=0;
scanf("%d%d",&n,&k);
memset(mp,-1,sizeof mp);
for(int i=1;i<=n;i++)
{
mp[i][i]=0;
}
for(int i=1;i<=n*(n-1)/2;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
mp[x][y]=w;
mp[y][x]=w;
}
dfs(k);
printf("%d\n",ans);
}
}