HDU6797 Tokitsukaze and Rescue(最短路+暴力)

仔细观察题目信息对做题帮助特别大。

本题一看数据范围不是很大,尤其是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;
}
View Code

 

posted @ 2020-08-30 22:55  朝暮不思  阅读(181)  评论(0编辑  收藏  举报