一开始想了个暴力骗到了50分的最大值.
就是一个连通块求拓扑序,然后只要保证最后一个位置是第一个位置所能到达的最远点.
那么设
q
[
i
]
q[i]
q[i]为最后拓扑序第
i
i
i项,我们直接令
p
[
q
[
i
]
]
=
q
[
i
−
1
]
p[q[i]]=q[i-1]
p[q[i]]=q[i−1]即可.(特别的,令
q
[
0
]
=
q
[
l
e
n
]
q[0]=q[len]
q[0]=q[len])
设
f
[
i
]
f[i]
f[i]是每一个点能到达的最多点数,那么显然这样构造是可以取到上界的.
但是这个就不好拓展到最小值.
下面讲另一种方法:参考blog
最大值:
我们显然让非叶子节点匹配儿子,然后叶子节点贪心匹配上一个非祖先节点,特别地,对于第一个叶子节点我们匹配 外向树根在环上的前驱.
我们用一个栈来存可以匹配的节点,那么只要能完美匹配,那么就能取到上界
∑
f
[
i
]
\sum f[i]
∑f[i].
对于完美匹配是否成立,我们只需考虑叶子节点,对于第一个叶子节点我们直接连上外向树根在环上的前驱.
否则,那么一定存在一个度数>1的中间点,连接两个叶子节点,因为弄完一棵子树一定会产生一个未匹配的点,那么我们直接连上即可.
最小值:
最大值的逆转置即为答案.
因为对于一个非叶子节点一定会被儿子匹配.
否则,对于环上的点,也尽可能地被前驱匹配.
这样显然可以取到最紧的界.
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define REP(i,a,b) for(int i=b;i>=a;i--)
#define FOR(i,n) rep(i,1,n)
#define ll long long
#define ull unsigned long long
#define gc getchar()
#define TP template<class o>
using namespace std;
const int N=1e5+10;
TP void qr(o &x) {
char c=gc; int f=1; x=0;
while(!isdigit(c)) {if(c == '-') f=-1; c=gc;}
while(isdigit(c))x=x*10+c-'0',c=gc;
x *= f;
}
TP void qw(o x) {
if(x < 0) putchar('-'),x=-x;
if(x / 10) qw(x/10);
putchar(x%10+'0');
}
TP void pr1(o x) {qw(x); putchar(' ');}
TP void pr2(o x) {qw(x); puts("");}
int n, a[N], b[N], c[N], deg[N], q[N], sta[N], top, cir[N], tot, f[N];
bool vis[N]; ll ans, mn;
struct edge{int y,next;} e[N]; int len,last[N];
void ins(int x,int y) {e[++len]=(edge){y,last[x]}; last[x]=len;}
void topsort() {
int l=1,r=0;
FOR(i,n) if(!deg[i]) q[++r]=i;
while(l<=r) {
int x=q[l++],y=a[x]; vis[x]=1;
if(!--deg[y]) q[++r]=y;
}
}
void dfs(int x,int fa) {
bool leaf=1;
ans += f[x]; mn += f[x];
for(int k=last[x],y;k;k=e[k].next)
if((y=e[k].y) ^ fa && !deg[y]) {
leaf=0;
f[y] = f[x] + 1;
dfs(y,x);
sta[++top]=y;
}
b[x]=sta[top--];
if(!leaf) mn -= f[x]-1;
else if(!fa) mn -= tot-2;
}
void solve(int st) {
cir[tot=1]=st; top=0;
for(int i=a[st];i!=st;i=a[i]) cir[++tot]=i;
cir[0]=cir[tot];
REP(i,1,tot) {
sta[++top]=cir[i-1];
f[cir[i]]=tot; dfs(cir[i],0);
}
FOR(i,tot) deg[cir[i]]=0;
}
int main() {
qr(n);
FOR(i,n) qr(a[i]),deg[a[i]]++,ins(a[i],i);
topsort();
FOR(i,n) if(deg[i]) solve(i);
FOR(i,n) c[b[i]]=i;
pr2(mn);
FOR(i,n) pr1(c[i]);
puts("");
pr2(ans);
FOR(i,n) pr1(b[i]);
return 0;
}