• 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
  • 相关阅读:
    计算机网络技术基础2
    java基础
    跨页传递参数或临时表的几种方法
    ASP.NET2.0文件上传以及图片处理总结篇 [转]
    正则表达式
    ASP.NET2.0中WEB应用程序的部署
    比较著名的.net技术论坛名称
    WordPress 插件开发实例 – 详细注释的 Widget 开发例子
    Java Applet签名验证
    Java Logging API Tutorial
  • 原文地址:https://www.cnblogs.com/CJLHY/p/8039716.html
Copyright © 2020-2023  润新知