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
原文地址:https://www.cnblogs.com/Opaser/p/4868170.html