(一)求一顆樹所有直徑上的所有點。
設f[i][0] 表示子樹第一長,f[i][1]表示子樹第二長,f[i][2]表示父節點到他的最長路徑,son[x]表示子樹最長路徑的兒子。
核心代碼:
void dp(int x,int fa)
{
p[x]=fa;
for(int i=first[x];i;i=e[i].next)
{
int w=e[i].to;
if(w==fa) continue;
dp(w,x);
if(f[w][0]+1>f[x][0])
{
f[x][1]=f[x][0];
f[x][0]=f[w][0]+1;
son[x]=w;
}
else f[x][1]=max(f[x][1],f[w][0]+1);
}
}
void dfs(int x,int fa)
{
if(x!=0)
{
f[x][2]=f[p[x]][2];
if(son[p[x]]==x) f[x][2]=max(f[x][2],f[p[x]][1]);
else f[x][2]=max(f[x][2],f[p[x]][0]);
f[x][2]++;
}
for(int i=first[x];i;i=e[i].next)
{
int w=e[i].to;
if(w==fa) continue;
dfs(w,x);
}
}
(二)錯排公式
f[i]=(n-1)*(f[n-2]+f[n-1]);
f[1]=0,f[2]=1;
證明:
設f[i]表示i個元素滿足錯排的方案數,
對於一個新元素 n,他一定不能放在n位置。
1.我們可以將n放在前面的任意一個位置k,即有(n-1)種方案。
2.既然n放在了一個位置k,那麼該位置原來的元素就要換一個位置。
如果他在n位置,那麼就是n個元素,除了k位置的n&n位置的k,還有n-2個元素要求滿足錯排,即f[n-2]
如果不在n位置,那麼就是n個元素,除了k位置的n,還有n-1個元素要求滿足錯排,即f[n-1]
整理的出公式:f[i]=(i-1)*(f[i-1]+f[i-2])
然後邊界條件手算一下就好了(1和2)。
(三) 編號小的元素在答案排列中儘量靠前==倒過來字典序最大