zoukankan      html  css  js  c++  java
  • Codeforces Round #319 (Div. 2) D

    Invariance of Tree

    题目大意:给你一个有1-n组成的序列p,让你构造一棵树,如果节点a和b之间有一条边,则p[a]和p[b]之间也有一条边。

    思路:没啥思路,看了题解菜爆。

    我们可以把1-n个数分到若干个集合里边,一个集合里边的元素要满足按顺序转移改变的性质,如果有其中一个集合的元素等于数量等于1

    或者其中一个集合的元素数量等于二,并且没有集合有奇数个元素。 因为我们需要用一个集合当作树的基准来构造,将其他集合的元素

    连到这个基准上,所以如果这个基准的元素大于三个他们之间必然成环,并且如果其他集合有奇数个元素,那么循环一圈后肯定会产生矛盾。

    还有要注意的一点是,一个集合不一定是一个圈,可能有一段出来的尾巴,那我们先从没有入度的点开始dfs就行了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    int base[2],p[N],vis[N],n;
    bool in[N];
    vector<int>ans;
    bool dfs(int cur,int step)
    {
        vis[cur]=step;
        ans.push_back(cur);
        if(!vis[p[cur]]) return dfs(p[cur],step+1);
        int t=step+1-vis[p[cur]];
        return base[0]==base[1] || t==1 || t%2==0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&p[i]);
            in[p[i]]=1;
            if(i==p[i]) base[0]=base[1]=i;
        }
        if(base[0]==0)
        {
            for(int i=1;i<=n;i++)
            {
                if(i==p[p[i]])
                {
                    base[0]=i;
                    base[1]=p[i];
                    break;
                }
            }
        }
        if(base[0]==0)  puts("NO");
        else
        {
            vis[base[0]]=vis[base[1]]=1;
            for(int i=1;i<=n;i++)
            {
                if(!in[i])
                {
                    if(!dfs(i,1))
                    {
                        puts("NO");
                        return 0;
                    }
                }
            }
            for(int i=1;i<=n;i++)
            {
                if(!vis[i])
                {
                    if(!dfs(i,1))
                    {
                        puts("NO");
                        return 0;
                    }
                }
            }
            puts("YES");
            if(base[0]!=base[1]) printf("%d %d
    ",base[0],base[1]);
            int len=ans.size();
            for(int i=0;i<len;i++) printf("%d %d
    ",base[i&1],ans[i]);
            puts("");
        }
    }
    View Code
  • 相关阅读:
    JVM基础系列第1讲:Java 语言的前世今生
    JVM基础系列开篇:为什么要学虚拟机?
    2018 精选文章集合
    如何唯一确定一个 Java 类?
    Java 中的 try catch 影响性能吗?
    不读大学也能成功,七个读大学的备用选择
    【中间件安全】IIS7.0 安全加固规范
    【中间件安全】Apache 安全加固规范
    Excel 保护工作表
    【应用安全】S-SDLC安全开发生命周期
  • 原文地址:https://www.cnblogs.com/CJLHY/p/8039716.html
Copyright © 2011-2022 走看看