P2597 [ZJOI2012]灾难——拓扑,倍增,LCA
最近想学支配树,但是基础还是要打好了的;
这道题是根据食物链链接出一个有向图的关系,求一个物种的灭绝会连带几种物种的灭绝;
求得就是一个点能支配几个点;
如果一个点没有食物了就会灭绝,那他的支配点就是他所有食物的LCA;
LCA死了,食物都死了,他也就死了;
我们先根据吃和被吃建图,连一条他和食物的有向边;
我们处理出拓扑序,入度为零的点就是终极捕食者;
重新建一个树,每个点支配的数量就是他为根的子树大小-1;
我们只需要将他和食物的LCA连边即可;这个时候我们连接的是反的,食物连向捕食者,这样子树大小才正确;
新加的虚拟节点没有影响,遍历树时很方便。
建立编号n+1的虚拟节点,将所有没有出边的光合食物连向这个点,以便以后求LCA;
注意每次都要更新f[][];
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; const int maxn=7e5+10; int pre[maxn*2],last[maxn],other[maxn*2],l; int pre2[maxn*2],last2[maxn],other2[maxn*2],l2; int n; void add(int x,int y) { l++; pre[l]=last[x]; last[x]=l; other[l]=y; } void add2(int x,int y) { l2++; pre2[l2]=last2[x]; last2[x]=l2; other2[l2]=y; } queue<int> q; int topo[maxn],sum,in_eage[maxn]; int dep[maxn],father[maxn]; int f[maxn][20]; void rmq(int x) { f[x][0]=father[x]; for(int i=1;i<=17;i++) { f[x][i]=f[f[x][i-1]][i-1]; } } int LCA(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=0;i<=17;i++) { if((dep[x]-dep[y])&(1<<i)) x=f[x][i]; } if(x==y) return x; for(int j=17;j>=0;j--) { if(f[x][j]!=f[y][j]) { x=f[x][j]; y=f[y][j]; } } return f[x][0]; } void toposort() { for(int i=1;i<=n;i++) { if(in_eage[i]==0) { q.push(i); } } while(!q.empty()) { int x=q.front(); q.pop(); topo[++sum]=x; for(int p=last[x];p;p=pre[p]) { int v=other[p]; in_eage[v]--; if(in_eage[v]==0) { q.push(v); } } } } void build() { dep[n+1]=1; father[n+1]=n+1; for(int i=n;i>=1;i--) { int x=topo[i]; if(last[x]==0) { dep[x]=2; father[x]=n+1; add2(n+1,x); f[x][0]=n+1; continue; } else { int lca=other[last[x]]; for(int p=last[x];p;p=pre[p]) { int v=other[p]; lca=LCA(lca,v); } father[x]=lca; add2(lca,x); dep[x]=dep[lca]+1; rmq(x); } } } int siz[maxn]; void dfs(int x) { siz[x]=1; for(int p=last2[x];p;p=pre2[p]) { int v=other2[p]; dfs(v); siz[x]+=siz[v]; } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); while(x) { in_eage[x]++; add(i,x); scanf("%d",&x); } } toposort(); build(); dfs(n+1); for(int i=1;i<=n;i++) { printf("%d\n",siz[i]-1); } return 0; }