题目在这里或者这里
分析题目,m只有n-1和n两种情况。
1、先看n-1的情况,在这种情况下,其实就是一棵树,要想求最小字典序的序列,我们只需要从1开始搜索(因为是无向边,无论哪一个节点都可以当作根节点),在该结点有多个分节点的情况下优先选择较小的节点即可,在搜索的过程中顺便把路径记录下来。在看当前节点的分节点的时候,这里可以考虑用一个vector数组去存,这样可以直接找到这个节点的所有相邻节点,还可以进行sort排序,遍历节点的时候可以从小到大。
2、再看m等于n的情况,在这种情况下,可以看作将m条边中的某一条割断之后继续像1一样进行搜索,然后取字典序最小的一个路径即可。为什么可以看作将某一条边割断呢?因为要联通n个点的话,其实只需要n-1条边就可以了,想不通的话,可以画一个带环的树来看看。至于为什么需要割断一条边,可以看图
如果我们不切断2、4这条边,那么得到的序列应该是1、2、4、3,但是如果我们切断了这条边,那么我们得到的序列就是1、2、3、4,比刚才的情况要小。可以用一个边结构体来存m条边,下边的时候可以直接遍历每条边,假设这条边被割断了,然后继续搜索即可,搜索完之后判断是否要更新ans数组
3、最后一点,记得开O2或者O3
代码如下:
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define ll long long
#define pii pair<ll,ll>
using namespace std;
//typedef long long int ll;
//const ll inf = 1e16;
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
vector<int> a[6000];
ll ans[6000];
ll temp[6000];
ll vis[6000];
struct node
{//储存边
ll from,to;
} edge[6000];
ll tot,du,dv,n,m;
void dfs1(ll u)
{//第一种情况的搜索
if(vis[u])
{
return ;
}
ans[tot++]=u;
vis[u]=1;
for(ll i=0; i<a[u].size(); i++)
{//遍历节点u的邻节点
ll v=a[u][i];
dfs1(v);
}
}
void dfs2(ll u)
{//第二种情况的搜索
if(vis[u])
{//如果这个点遍历过,直接退出
return ;
}
temp[tot++]=u;
vis[u]=1;
for(ll i=0; i<a[u].size(); i++)
{
ll v=a[u][i];
if((u==du&&v==dv)||(v==du&&u==dv))
{//如果这条边是被割断的,直接跳过
continue;
}
dfs2(v);
}
}
ll check()
{//检查是否更新答案
for(ll i=0; i<n; i++)
{
if(temp[i]<ans[i])
{//如果更小,更新
return 1;
}
if(temp[i]>ans[i])
{//如果比ans更大,不更新
return 0;
}
}
return 0;
}
void fuzhi()
{
for(ll i=0; i<n; i++)
{
ans[i]=temp[i];
}
}
int main()
{
ll u,v;
scanf("%lld%lld",&n,&m);
for(ll i=1; i<=m; i++)
{
scanf("%lld%lld",&u,&v);
a[u].push_back(v);
a[v].push_back(u);
edge[i].from=u;
edge[i].to=v;
}
for(ll i=1; i<=n; i++)
{//对每个节点的邻接点排序
sort(a[i].begin(),a[i].end());
}
if(m==n-1)
{
tot=0;
dfs1(1);
}
else
{
memset(ans,0x3f,sizeof(ans));
for(ll i=1; i<=m; i++)
{
memset(vis,0,sizeof(vis));
tot=0;
du=edge[i].from;
dv=edge[i].to;
dfs2(1);
if(tot<n-1)
{//如果图被割断,变成两个部分,直接找下一种情况
continue;
}
if(check())
{
fuzhi();
}
}
}
for(ll i=0; i<n-1; i++)
{
printf("%lld ",ans[i]);
}
printf("%lld\n",ans[n-1]);
return 0;
}