luogu5022 [NOIp2018]旅行 (dfs)

时间:2021-12-17 20:15:54

m=n-1的时候,就直接贪心地dfs就可以

m=n的话,就可以枚举删掉一条边,然后照着m=n-1做

$O(n^2)$大概能过

(然而我眼瞎看不到m<=n)

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int maxn=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){
if(c=='-') neg=-;
c=getchar();
}while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M;
int eg[maxn*][],egh[maxn],ect=;
int ans[maxn],del[]; inline void adeg(int a,int b){
eg[++ect][]=b,eg[ect][]=egh[a];egh[a]=ect;
}
bool flag[maxn];
bool dfs(int x,int f){
ans[++ans[]]=x;flag[x]=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];
if(b==f||(x==del[]&&b==del[])||(x==del[]&&b==del[])) continue;
if(flag[b]) return ;
if(dfs(b,x)) return ;
}return ;
} inline void solve1(){
dfs(,);
for(int i=;i<=N;i++) printf("%d ",ans[i]);
} int lst[maxn];
inline void solve2(){
for(int i=,j;i<=N;i++){
del[]=i;
for(int k=egh[i];k;k=eg[k][]){
del[]=eg[k][];
memset(flag,,sizeof(flag));
ans[]=;
if(dfs(,)) continue;
if(ans[]<N) continue;
bool b=;
for(j=;j<=N;j++){
if(lst[j]==ans[j]) continue;
if(lst[j]&&lst[j]<ans[j]) b=;
break;
}
if(b) memcpy(lst+j,ans+j,*(N-j+));
} }
for(int i=;i<=N;i++)
printf("%d ",lst[i]);
} int main(){
// freopen("travel.in","r",stdin);
// freopen("travel.out","w",stdout);
int i,j,k;
N=rd(),M=rd();
for(i=;i<=M;i++){
int a=rd(),b=rd();
q[a].push(b),q[b].push(a);
}
for(i=;i<=N;i++){
while(!q[i].empty()){
int p=q[i].top();q[i].pop();
adeg(i,p);
}
}
if(M==N-) solve1();
else solve2();
return ;
}