做这题一定要看数据范围,从数据范围中可以得到,这个图要么是一棵树,要么是一棵基环树(树上多一条边)
对于一棵树,每一步贪心取最小节点就行了。
对于一棵基环树,你只需要枚举多的那条边删去按正常的树做。注意删去这条边后剩下的图应该联通,意思就是不能删去割边,所以先把割边找出来然后枚举每条非割边,然后就做完了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int n,m,ans[5005],an[5005],tot,cnt,d[5005][2];
int dfn[5005],low[5005],fa[5005];
bool f[5005],f1[5005][5005],f2[5005][5005];
int x1[5005],y1[5005];
vector<int>g[5005];
inline void dfs(int x)
{
ans[++tot]=x;
f[x]=1;
for(int i=0;i<g[x].size();i++)
if(!f[g[x][i]])
dfs(g[x][i]);
}
inline void dfs2(int x)
{
an[++tot]=x;
f[x]=1;
for(int i=0;i<g[x].size();i++)
if(!f[g[x][i]]&&!f1[x][g[x][i]])
dfs2(g[x][i]);
}
inline void dfs1(int x)
{
dfn[x]=low[x]=++tot;
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(!dfn[v])
{
fa[v]=x;
dfs1(v);
low[x]=min(low[x],low[v]);
if(low[v]>dfn[x])
{
cnt++;
f2[v][x]=f2[x][v]=1;
}
}
else if(fa[x]!=v)
low[x]=min(low[x],dfn[v]);
}
}
inline bool check()
{
for(int i=1;i<=n;i++)
if(an[i]!=ans[i])
return an[i]<ans[i];
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
x1[i]=x,y1[i]=y;
g[x].push_back(y);
g[y].push_back(x);
}
for(int i=1;i<=n;i++)
sort(g[i].begin(),g[i].end());
dfs(1);
if(n==m)
{
tot=0;
dfs1(1);
for(int i=1;i<=m;i++)
if(!f2[x1[i]][y1[i]])
{
f1[x1[i]][y1[i]]=1;f1[y1[i]][x1[i]]=1;
tot=0;
memset(f,0,sizeof(f));
dfs2(1);
if(check())
memcpy(ans,an,sizeof(an));
f1[x1[i]][y1[i]]=0;f1[y1[i]][x1[i]]=0;
}
}
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
}