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

                                                                                                              E

    A tree of size n is an undirected connected graph consisting of n vertices without cycles.

    Consider some tree with n vertices. We call a tree invariant relative to permutation p = p1p2... pn, if for any two vertices of the tree u andv the condition holds: "vertices u and v are connected by an edge if and only if vertices pu and pv are connected by an edge".

    You are given permutation p of size n. Find some tree size n, invariant relative to the given permutation.

    题意说的是给了一个数列p1p2... pn 组成的数是1到n。然后让你构造一棵N个点的树要保证树中 u和v存在路径, 那么在这颗树种pu,和pv也必须存在路径

    想法:   如果pv pu 有连线 那么P[pv] P[pu]也要有联系,我们发现这样会是一个循环,这样我们就可以知道,在同一个循环内除了 长度为1 或者2的可以自己和自己连接,其他都必须和1 或者2连接

    如果最小的一个循环节大小为1的循环节,那么就有解,你可以让他去连接除了他自己之外的任意一个循环节,这样算算边完全是n-1条

    如果最小的一个循环节为2的那么其他的存在循环节的话必须为2的倍数,你可以画一下他们只要不是倍数关系,可定乱套了。

    如果最小的一个循环节大于2肯定无解,因为他要和自己连都已经形成环了

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    #include <vector>
    #include <set>
    using namespace std;
    const int maxn=100005;
    struct edg{
      int a,b;
      edg(int ca=0,int cb=0){
        if(ca>cb)swap(ca,cb);
        a=ca; b=cb;
      }
      bool operator == (const edg &rhs)const{
        return a==rhs.a&&b==rhs.b;
      }
      bool operator <(const edg &rhs)const {
        return a<rhs.a||(a==rhs.a&&b<rhs.b);
      }
    };
    vector<int>G[maxn];
    int A[maxn],n;
    bool use[maxn];
    set<edg>Q;
    void bfs(int root, int to)
    {
        while(true){
            edg e=edg(root,to);
            if(Q.count(e))return ;
            else Q.insert(e);
            root=A[root];
            to=A[to];
        }
    }
    void solve1(){
        int root=G[1][0];
        for(int i=1; i<G[1].size(); i++)
        {
            edg a=edg(root,G[1][i]);
            Q.insert(a);
        }
        for(int i=2; i<=n; i++)
        {
            int siz=G[i].size();
            for(int j=0; j<siz; j++)
            {
                 int to=G[i][j];
                 bfs(root,to);
            }
        }
    }
    void solve2()
    {
        int root1=G[2][0];
        int root2=A[root1];
        edg e=edg(root1,root2);
        Q.insert(e);
        for(int i=1; i<G[2].size(); i++)
            bfs(root1,G[2][i]);
       for(int i=3; i<=n; i++)
        {
            int siz=G[i].size();
            for(int j=0; j<siz; j++)
            {
                 int to=G[i][j];
                 bfs(root1,to);
            }
        }
    }
    int main()
    {
    
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&A[i]);
        for(int i=1; i<=n; i++)
        {
            if(use[i])continue;
            int siz=0,L=A[i];
            while(use[L]==false){
                 use[L]=true;
                siz++;
                L=A[L];
            }
            G[siz].push_back(i);
        }
        if(G[1].size()==0&&G[2].size()==0){
             puts("NO"); return 0;
        }
        if(G[1].size())solve1();
        else {
            for(int i=2; i<=n; i++)if(G[i].size()){
                if(i%2){
                    puts("NO");return 0;
                }
            }
            solve2();
        }
        puts("YES");
        set<edg>::iterator it;
        for(it = Q.begin() ; it!=Q.end(); ++it)
        {
            edg e = *it;
            printf("%d %d
    ",e.a,e.b);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    WeUI——switch开关转换
    WeUI——单选框
    WeUI——CheckBox表单复选框
    WeUI——表单输入框状态
    WeUI——表单验证码
    详细介绍 C# 中的方法和参数
    C# 中类的基本概念
    C# 中的类型和变量
    学习 C# 从 Hello World 开始吧
    C# 和 .NET Core 的关系
  • 原文地址:https://www.cnblogs.com/Opaser/p/4868170.html
Copyright © 2011-2022 走看看