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\n",e.a,e.b); } return 0; }