D. Artsem and Saunders
一个变换题
给定f(x),[1,n]->[1,n]
构造g(x),h(x)满足:
g(h(x))=x [1,n]->[1,m]
h(g(x))=f(x) [1,m]->[1,n]
根据已知条件,等效替换变形:
h(g(h(x)))=f(h(x))
=>h(x)=f(h(x))
=>h(g(x))=f(h(g(x)))
=>f(x)=f(f(x)) //是不是有点类似并查集找爸爸
另一方面:
g(h(g(x)))=g(x)
=>g(x)=g(f(x))
这里我们又可以发现f,g,h三个函数的值域其实都是[1,m],等价于将n个元素分为m类
那么题目意思是不是可以转化成:
f(i):找i这个元素的爸爸元素是谁
g(i):找元素i属于哪一类
h(i):找第i类的爸爸元素是谁
这不就是很经典的(排名<<=>>权值)互换函数么
int n, m; int f[N], g[N], h[N]; int vis[N]; int main() { #ifndef ONLINE_JUDGE file("test"); #endif sdf(n); For(i, 1, n) sdf(f[i]); For(i, 1, n) { if (f[f[i]] != f[i]) { cout << -1; return 0; } if (!vis[f[i]]) h[++m] = f[i], g[f[i]] = m,vis[f[i]]=1; g[i] = g[f[i]]; } cout << m << endl; For(i, 1, n) cout << g[i] << " "; cout << endl; For(i, 1, m) cout << h[i] << " ";