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;