QAQ
【题目分析】
好菜好菜。。。。。fAKe dalao ldx差点就AK了啊。。。。。。。再看看自己的分。。。。。【捂脸】
之前还做过同类型的题啊,蓝瘦。
正难则反,既然删点难以维护,就考虑向图中加点,直接离线处理。
首先读入所有操作,统计最后剩下的所有点产生的贡献,合并两个联通块产生的贡献就是两个联通块的权值和的积,所以维护一下就好了,至于每次摧毁的点要记得连通后要变成未摧毁的,调了半天。。。。。
【代码~】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=1e6+10;
const LL MOD=1e9+7;
LL n,m,cnt,ans[MAXN];
LL vis[MAXN],des[MAXN],sum;
LL head[MAXN],to[MAXN<<1],nxt[MAXN<<1];
vector<LL> tim[MAXN];
struct father{
LL fat,sum;
}fa[MAXN];
LL Read()
{
LL i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
void sc(LL x)
{
if(x>=10)
sc(x/10);
putchar(x%10+48);
}
void add(LL x,LL y)
{
nxt[cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
cnt++;
}
LL find(LL x)
{
if(x==fa[x].fat)
return x;
return fa[x].fat=find(fa[x].fat);
}
void merge(LL x,LL y)
{
sum=(sum+fa[x].sum*fa[y].sum%MOD)%MOD;
fa[x].sum=(fa[x].sum+fa[y].sum)%MOD;
fa[y].fat=x;
}
void dfs(LL u)
{
vis[u]=1;
for(LL i=head[u];i!=-1;i=nxt[i])
{
LL v=to[i];
if(!vis[v]&&!des[v])
{
LL x=find(u),y=find(v);
merge(x,y);
dfs(v);
}
}
}
void addpoint(LL u)
{
des[u]=0;
for(LL i=head[u];i!=-1;i=nxt[i])
{
LL v=to[i];
if(!des[v])
{
LL x=find(u),y=find(v);
merge(x,y);
}
}
}
int main()
{
memset(head,-1,sizeof(head));
n=Read(),m=Read();
for(LL i=2;i<=n;++i)
{
LL fath=Read();
add(i,fath);
add(fath,i);
}
for(LL i=1;i<=n;++i)
fa[i].fat=fa[i].sum=i;
for(LL i=1;i<=m;++i)
{
LL total=Read();
for(LL j=1;j<=total;++j)
{
LL id=Read();
des[id]=1;
tim[i].push_back(id);
}
}
for(LL i=1;i<=n;++i)
if(!vis[i]&&!des[i])
dfs(i);
ans[m]=sum;
for(LL i=m;i;--i)
{
LL siz=tim[i].size();
for(LL j=0;j<siz;++j)
addpoint(tim[i][j]);
ans[i-1]=sum;
}
for(LL i=0;i<=m;++i)
cout<<ans[i]<<'\n';
return 0;
}