zoukankan      html  css  js  c++  java
  • [NOIP2018]旅行(数据加强版)(图论+基环树)

    数据范围多了2个0就是不一样,O(n^2)只能68分了。(其中60分是n=m+1和原题一样的做法送的),这题直接从NOIP难度变为NOI Plus难度了
    不说废话直接写题解:
    首先dfs一遍找到环,然后和n=m+1一样从1号点访问,然后跑到环以后,对于环上的点,可以执行仅一次返回到第一次到达环上的点的操作。所以dfs记录的时候记录下次访问的点就可以,因为退回操作后只要退回途中下面有点,那么就必须访问,讨论一下退回途中访问的第1个点,比较其余环上下一个点的大小就行了。注意dfs时要打标记(否则可能会有锅)。

    注意:数据有毒,要写读入优化+适当卡常数X过去(没写读优被卡成96的我),最后运行时间最长的932ms通过,如果多交几次发现还有没通过的时候(不管了)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e5+7;
    int n,m,top,k,cnt,cut,a[N],b[N],cir[N],s[N],g[N],vis[N];
    vector<int>v[N];
    inline int read()
    {
        int x=0,w=0;
        char ch=0;
        while(!isdigit(ch))w|=ch=='-',ch=getchar();
        while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return w?-x:x;
    }
    void dfs(int u,int fa)
    {
        a[++top]=u;
        for(int i=0;i<v[u].size();++i)if(v[u][i]!=fa)dfs(v[u][i],u);
    }
    void getcir(int x,int fa)
    {
        s[++top]=x;
        vis[x]=1;
        int sz=v[x].size();
        for(int i=0;i<sz;++i)
        if(v[x][i]!=fa)
        {
            if(vis[v[x][i]])
            {
                k=1;
                while(s[top]!=v[x][i])g[++cnt]=s[top--];
                g[++cnt]=v[x][i];
                return;
            }
            getcir(v[x][i],x);
            if(k)return;
        }
        vis[s[top--]]=0;
    }
    void dfs2(int x,int k,int fa)
    {
        a[++top]=x,vis[x]=1;
        int sz=v[x].size()-1;
        for(int i=0;i<=sz;++i)b[i]=v[x][i];
        v[x].clear();
        for(int i=0;i<=sz;++i)
        if(!vis[b[i]])v[x].push_back(b[i]);
        sz=v[x].size()-1;
        for(int i=0;i<=sz;++i)
        if(!vis[v[x][i]])
        {
            if(i==sz&&cir[v[x][i]]&&!cut&&v[x][i]>k&&cir[fa]){cut=1;return;}
            if(i<sz-1)dfs2(v[x][i],v[x][i+1],x);
            else if(i==sz)dfs2(v[x][i],k,x);
            else{
                int y=i+1;
                if(cir[v[x][y]]&&!cut&&v[x][y]>k&&cir[fa])dfs2(v[x][i],k,x);
                else dfs2(v[x][i],v[x][y],x);
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,x,y;i<=m;i++)v[x=read()].push_back(y=read()),v[y].push_back(x);
        for(int i=1;i<=n;i++)sort(v[i].begin(),v[i].end());
        if(m==n-1)
        {
            dfs(1,0);
            for(int i=1;i<=n;i++)printf("%d ",a[i]);
        }
        else{
            getcir(1,0);
            for(int i=1;i<=cnt;i++)cir[g[i]]=1;
            top=0;
            memset(vis,0,sizeof vis);
            dfs2(1,n+1,0);
            for(int i=1;i<=n;i++)printf("%d ",a[i]);
        }
    }
    View Code
  • 相关阅读:
    火车头入库SQLSERVER时数据库配置的问题
    帝国CMS在封面、列表调用栏目别名的方法
    电子商务关键数字优化(线上部分,下)
    电子商务关键数字优化(线上部分,上)
    创业公司Celebrity Performance 评估名人影响力
    SQLautoReview
    互联网/电子商务数据分析师的十大误区
    Amazon Silk 你所不知道的在Kindle背后的大数据
    Nike可穿戴的大数据玩法
    [转]Decide.com是怎么做商品价格预测的
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10159453.html
Copyright © 2011-2022 走看看