BZOJ2815: [ZJOI2012]灾难(支配树)

来源:互联网 发布:外星人源码论坛eenot 编辑:程序博客网 时间:2024/05/17 23:07

传送门

题解:
支配树裸题了。。

写这篇博客只是为了提供一份支配树的代码。。

#include<bits/stdc++.h>using namespace std;inline int rd(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;}inline void W(int x){    static int buf[50];    if(!x){putchar('0');return;}    if(x<0){putchar('-');x=-x;}    while(x){buf[++buf[0]]=x%10;x/=10;}    while(buf[0])putchar(buf[buf[0]--]+'0');}inline void gmin(int &x,int y){(x>y)?(x=y):0;}const int N=1e5+50;int rt,n,sdom[N],idom[N],id[N],dfn[N],mnsd[N],tot,anc[N],fa[N];vector<int>pre[N],buc[N],edge[N];struct DominatorTree{    int sze[N],v[N],nt[N],g[N],ec;    inline void add(int x,int y){nt[++ec]=g[x];g[x]=ec;v[ec]=y;}    inline void dfs(int x){        sze[x]=1;        for(int j=g[x];j;j=nt[j])dfs(v[j]),sze[x]+=sze[v[j]];    }}g;inline void dfs(int x,int f=0){    dfn[x]=++tot;id[tot]=x;fa[x]=f;    sdom[x]=mnsd[x]=anc[x]=x;    for(int e=edge[x].size()-1;e>=0;e--){        int v=edge[x][e];        if(dfn[v])continue;        dfs(v,x);    }}inline void getanc(int p){    if(anc[p]!=p)getanc(anc[p]);    if(dfn[sdom[mnsd[anc[p]]]]<dfn[sdom[mnsd[p]]])mnsd[p]=mnsd[anc[p]];    anc[p]=anc[anc[p]];}inline int eval(int p){  //获取到根节点路径上sdom最小的点    getanc(p);    return mnsd[p];}int main(){    n=rd();rt=n+1;    for(int i=1;i<=n;i++){        int cnt=0,x=rd();        while(x){            pre[i].push_back(x);            edge[x].push_back(i);            ++cnt;x=rd();        }        if(!cnt){            pre[i].push_back(rt);            edge[rt].push_back(i);        }    }    dfs(rt);fa[rt]=rt;    for(int i=tot;i>=1;i--){        int u=id[i];        for(int j=pre[u].size()-1;j>=0;j--){            int t=eval(pre[u][j]);            if(dfn[sdom[t]]<dfn[sdom[u]])sdom[u]=sdom[t];        }        anc[u]=fa[u];int f=fa[u];        buc[sdom[u]].push_back(u);        for(int j=buc[f].size()-1;j>=0;j--){ //此时该节点所有子树以父节点为半支配点的点路径全部已经处理出            int v=buc[f][j];int t=eval(v);            if(dfn[sdom[t]]<dfn[sdom[v]])idom[v]=t;            else idom[v]=sdom[v];        }        buc[f].clear();    }    for(int i=2;i<=tot;i++){        int u=id[i];        if(idom[u]!=sdom[u])idom[u]=idom[idom[u]];        g.add(idom[u],u);    }    g.dfs(id[1]);    for(int i=1;i<=n;i++){        W(g.sze[i]-1);putchar('\n');    }}
原创粉丝点击