【NOIP2018】旅行

版权声明:本文为博主原创文章。 https://blog.csdn.net/qq_37657307/article/details/84196556

题目链接

做这题一定要看数据范围,从数据范围中可以得到,这个图要么是一棵树,要么是一棵基环树(树上多一条边)

对于一棵树,每一步贪心取最小节点就行了。

对于一棵基环树,你只需要枚举多的那条边删去按正常的树做。注意删去这条边后剩下的图应该联通,意思就是不能删去割边,所以先把割边找出来然后枚举每条非割边,然后就做完了。

#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]);
}

猜你喜欢

转载自blog.csdn.net/qq_37657307/article/details/84196556