Noip2018 D2T1 P5022 题解

P5022旅行 题解

标签(空格分隔): 题解


Noip2018 D2T1 P5022 旅行

Subtask 1: 60 points
题目条件\(m=n-1\),说明此时数据构成一棵树,搜索路径无需回溯,将每个节点所连的其他节点排序后,直接\(O(n)\)地通过dfs记录路径

void dfs(int u){
    vis[u]=true;
    ans[++p]=u;
    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(!vis[v]) dfs(v);
    }
}
//排序直接用sort给vector排序
for(int i=1;i<=n;i++)
    sort(vec[i].begin(),vec[i].end());

subtask 2:88 points
此时\(m=n\),构成基环树,暴力枚举\(O(n^2)\)删边,每次进行dfs,得到路径后与当前最优值比较即可

void _dfs(int u){
    vis[u]=true;
    tp[++p]=u;
    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(vis[v]) continue;
        if((u==x&&v==y)||(u==y&&v==x)) continue;
        _dfs(v);
    }
}
bool check(){
    for(int i=1;i<=n;i++)
        if(ans[i]!=tp[i])
            return tp[i]<ans[i];
    return false;
}
for(int i=1;i<=m;i++){
    p=0;flag=false;
    x=edge[i][0];y=edge[i][1];
    memset(vis,0,sizeof vis);
    _dfs(1);
    if(p<n) continue; //判断是否能构成一条完整的路径
    if(ans[1]==inf) memcpy(ans,tp,sizeof tp);
    else if(check()) memcpy(ans,tp,sizeof tp);
}

subtask 3:100 points
dfs时进行剪枝,若出现第一个大于最优值的编号,立刻return

if(tp[p]<ans[p]) flag=true; //如果已经比答案更优,则不需剪枝
if(!flag && tp[p]>ans[p]) return;
posted @ 2019-04-20 12:52  zyh-etr  阅读(152)  评论(0编辑  收藏  举报