链接:https://www.acwing.com/problem/content/536/
分析:
n是5000,可以搞个 O ( n 2 ) O(n^2) O(n2)的做法。
要求字典序最小,可以先预处理一下,对每一层排个序,让每一层的节点被从小到大遍历。
n = m n =m n=m时,就是一棵树,题目中的字典序就是dfs序,直接每一层按从小到大搜索就可以。
n = m + 1 n=m+1 n=m+1时,这棵树中就形成了环,是一颗基环树。
在有环的时候搜就会重复,那就每次删除一条边,删除后再搜索当前树的dfs序,如果发现dfs序比已经保存的小,就更新,如果大了就直接剪枝掉。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5005;
#define INF 0x3f3f3f3f
struct edge
{
int u,v;
void add(int a,int b){
u = a;
v = b;
}
}e[maxn];
vector<int> g[maxn];
int ans[maxn];
int vis [maxn];
int cnt = 1;
int flag;
int del_u,del_v;
int dfs(int u,int fa){
if(!flag){
if(u > ans[cnt])
return 1;
if(u < ans[cnt])
flag = 1;
}
vis[u] = 1;
ans[cnt++] = u;
for(auto v: g[u]){
if(vis[v])
continue;
if((u == del_u && v == del_v) || (u == del_v && v == del_u))
continue;
if(dfs(v,u)) return 1;
}
return 0;
}
int main()
{
int n,m,u,v;
cin>>n>>m;
memset(ans,INF,sizeof(ans));
for(int i = 0;i < m; i++ ){
cin>>u>>v;
e[i].add(u,v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i = 1;i <= n; i++)
sort(g[i].begin(),g[i].end());
if(n - 1 ==m ){
dfs(1,0);
for(int i = 1;i <= n; i++)
cout<<ans[i]<<" ";
}
else{
for(int i = 0;i < m; i++){
memset(vis,0,sizeof(vis));
del_u = e[i].u;
del_v = e[i].v;
flag = 0;
cnt = 1;
dfs(1,0);
}
for(int i = 1;i <= n; i++)
cout<<ans[i]<<" ";
}
return 0;
}