[ZJOI2815]灾难 建树+动态LCA+树上dp

来源:互联网 发布:mac windows 双系统 编辑:程序博客网 时间:2024/06/07 10:27

植物的生存依赖关系可以构成一棵树
把它建出来就行啦

#define lim 200#define N 200050#define M 1000050using namespace std;inline int rd() {    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,cnt1,cnt2,cnt3,h[N],H[N],head[N],D[N],Jump[N],fa[N],siz[N],d[N];queue<int> q;struct Edge{ int b,next; }e[M],E[M],edge[M];void add(int a,int b) { e[++cnt1] = (Edge){b,h[a]}; h[a] = cnt1; }void ADD(int a,int b) { E[++cnt2] = (Edge){b,H[a]}; H[a] = cnt2; }void Add(int a,int b) {    edge[++cnt3] = (Edge){b,head[a]}; head[a] = cnt3;}int LCA(int u,int v) {    if (u == -1) return v;    if (D[u] < D[v]) swap(u,v);    while (u && D[ Jump[u] ] >= D[v]) u = Jump[u];    while (u && D[u] > D[v]) u = fa[u];    if (u == v) return u;    while (u && v && Jump[u] != Jump[v])        u = Jump[u], v = Jump[v];    while (u && v && fa[u] != fa[v])        u = fa[u], v = fa[v];    return fa[u];}void dfs(int u) {    siz[u] = 1;    for (int i=H[u];i;i=E[i].next)        dfs( E[i].b ), siz[u] += siz[ E[i].b ];}int main() {    n = rd();    for (int _=1;_<=n;_++)        for (int x=rd();x;x=rd()) add(_,x), Add(x,_), d[_]++;    for (int _=1;_<=n;_++) if (!d[_]) q.push(_);    while (!q.empty()) {        int u = q.front(), f = -1; q.pop();        for (int i=h[u];i;i=e[i].next) f = LCA(f, e[i].b);        for (int i=head[u];i;i=edge[i].next)            if (--d[ edge[i].b ] == 0) q.push( edge[i].b );        f=(f==-1)?0:f;        fa[u] = f; D[u] = D[f] + 1;        Jump[u] = ( D[Jump[f]]-D[u]>lim ) ? u : Jump[f];        ADD(f,u);    }    dfs(0);    for (int _=1;_<=n;_++) printf("%d\n",siz[_]-1);    return 0;} 
0 0
原创粉丝点击