題目
思路
換個問題,求每個集合最後的大小。我們發現,如果將 u,v 合併,那麼 f[u]=f[v]=f[u]+f[v]−f[u]⋂f[v]
而 f[u]⋂f[v] 之和上一次 u,v 合併的結果有關,於是我們可以對每條邊單獨記錄一個數,表示上一次合併這條邊的結果
回到原問題,我們發現,每個點被哪些集合包含,只需要倒敘處理新問題就可以得到原問題的答案
代碼
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+77;
int n,m,p[N],x[N],y[N],f[N],g[N];
void write(int x,int flag)
{
printf("%d",x);
if(flag==0) putchar(' ');
else puts("");
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<n; i++) scanf("%d%d",&x[i],&y[i]);
for(int i=1; i<=m; i++) scanf("%d",&p[i]);
for(int i=1; i<=n; i++) f[i]=1;
for(int i=m; i>=1;--i)
{
int u=x[p[i]], v=y[p[i]];
f[u]=f[v]=f[u]+f[v]-g[p[i]];
g[p[i]]=f[u];
}
for(int i=1; i<=n; i++) write(f[i],i==n);
}