[NOIP2018] 旅行 题解

明显要以 \(1\) 为起点。

原图是树

这种情况下,走路不能回头,只能用 \(dfs\) 的思路走。当然肯定每次都走较小的那棵子树,\(vector\) 存图后排序即可达到这种效果。

时间复杂度 \(O(n\log m)\)

原图是基环树

明显可以分别考虑将所有边断掉后的情况,取字典序最小的。

时间复杂度 \(O(nm)\)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5005;
int n,m,vis[N],u[N],v[N];
int k,c,d,ans[N],b[N],f;
vector<int>g[N];
void dfs(int x){
    b[++k]=x;
    if(ans[k]>b[k]) f=1;
    if(ans[k]<b[k]&&!f){
        f=-1;
        return;
    }
    vis[x]=1;
    for(int i=0;i<g[x].size();i++){
        int y=g[x][i];
        if(x==c&&y==d) continue;
        if(x==d&&y==c) continue;
        if(!vis[y]) dfs(y);
        if(f==-1) return;
    }
}int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>u[i]>>v[i];
        g[u[i]].push_back(v[i]);
        g[v[i]].push_back(u[i]);
    }for(int i=1;i<=n;i++)
        sort(g[i].begin(),g[i].end());
    memset(ans,0x3f,sizeof(ans));
    if(m==n-1){
        dfs(1);
        for(int i=1;i<=k;i++)
            cout<<b[i]<<" ";
        return 0;
    }for(int i=1;i<=m;i++){
        memset(vis,0,sizeof(vis));
        memset(b,0x3f,sizeof(b));
        f=k=0;c=u[i];d=v[i];
        dfs(1);if(k<n) continue;
        for(int j=1;j<=n;j++)
            ans[j]=b[j];
    }for(int j=1;j<=n;j++)
        cout<<ans[j]<<" ";
    return 0;
}
posted @ 2024-04-14 09:15  长安一片月_22  阅读(7)  评论(0编辑  收藏  举报