仔细观察题目信息对做题帮助特别大。
本题一看数据范围不是很大,尤其是k很小,第一想法是能否把删除的边枚举出来每个做一遍
但是一算复杂度显然不太正确,题目当中重要的信息是,边权随机,这启发着我们最短路上的边数不会很多。
并且我们的目标是把最短路变长,因此显然我们要删除最短路的边,重复k次这样的操作就能获得答案
虽然答案套了个k次方,但是因为边权随机,所以最终的复杂度并不会很高。况且题目给了8秒。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> pll; const int N=5e5+10; const int inf=0x3f3f3f3f; const int mod=1e9+7; int h[110],e[110],ne[110],w[110],idx; int dis[110],st[110]; int n,k; int ans=0; int pre[110]; map<pll,int> m1; int dd[110][110]; void dij(int s){ priority_queue<pll,vector<pll>,greater<pll> > q; memset(dis,0x3f,sizeof dis); memset(st,0,sizeof st); dis[s]=0; q.push({0,1}); pre[1]=0; while(q.size()){ auto t=q.top(); q.pop(); if(st[t.second]) continue; st[t.second]=1; for(int i=1;i<=n;i++){ if(i==t.second|| st[i]) continue; if(dis[i]>dis[t.second]+dd[t.second][i]){ pre[i]=t.second; dis[i]=dis[t.second]+dd[t.second][i]; q.push({dis[i],i}); } } } } void dfs(int u){ if(u==0){ dij(1); ans=max(ans,dis[n]); return ; } dij(1); vector<int> num; num.clear(); int pt=n; while(pt!=1){ num.push_back(pt); pt=pre[pt]; } num.push_back(1); for(int i=(int)num.size()-1;i>0;i--){ int mem=dd[num[i]][num[i-1]]; dd[num[i]][num[i-1]]=dd[num[i-1]][num[i]]=0x3f3f3f3f; dfs(u-1); dd[num[i]][num[i-1]]=dd[num[i-1]][num[i]]=mem; } } int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ ans=0; cin>>n>>k; int i; for(i=1;i<=n*(n-1)/2;i++){ int a,b,c; cin>>a>>b>>c; dd[a][b]=dd[b][a]=c; } dfs(k); cout<<ans<<endl; } return 0; }