http://acm.hdu.edu.cn/showproblem.php?pid=6797
题意:最多50个点的完全图,删k(最多5)条边,求最大的最短路,边权范围内随机。
思路:先删一条边,必定有一条在最短路上,否则走这条还是最短。删这条边后,再找最短路,再删一边一定是在这次的最短路是,否则走这条还是最短,这样递归k层。复杂度是
O
(
n
2
∗
n
k
)
O(n^2 * n^k)
O(n2∗nk),最大
2500
∗
5
0
5
2500*50^5
2500∗505,看似不行,实际上就是暴力,因为边权随机,所以大部分最短路都比较短。
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int T,n,k,d[55][55];
bool link[55][55];
int dis[55],in[55],from[55];
int ans;
void spfa()
{
queue<int> q;
for(int i=2;i<=n;i++)
dis[i]=INF;
dis[1]=0;in[1]=true;q.push(1);
int u,v;
while(!q.empty())
{
u=q.front();q.pop();
for(v=1;v<=n;v++)
if(link[u][v] && dis[v]>dis[u]+d[u][v])
{
dis[v]=dis[u]+d[u][v];from[v]=u;
if(!in[v])
in[v]=true,q.push(v);
}
in[u]=false;
}
}
void dfs(int x)
{
if(x>k)
{
spfa();
ans=max(ans,dis[n]);
return;
}
spfa();
int u=n;
vector<int> path;
while(u)
{
path.push_back(u);
u=from[u];
}
for(int i=0;i<path.size()-1;i++)
{
link[path[i]][path[i+1]]=link[path[i+1]][path[i]]=0;
dfs(x+1);
link[path[i]][path[i+1]]=link[path[i+1]][path[i]]=1;
}
}
int main()
{
//freopen("input.in","r",stdin);
cin>>T;
while(T--)
{
cin>>n>>k;
int u,v,w;
for(int i=1;i<=n*(n-1)/2;i++)
{
cin>>u>>v>>w;
d[u][v]=d[v][u]=w;
link[u][v]=link[v][u]=1;
}
ans=0;
dfs(1);
cout<<ans<<endl;
}
}