BZOJ2815: [ZJOI2012]灾难

一个月前打的
今天才调试好。。。
居然是一个SB错误 重建树的深度没有修改。。。

#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;


char c;
inline void read(int &a)
{
    a=0;do c=getchar();while(c<'0'||c>'9');
    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();

} 
struct Chain
{
    int u;bool Check;
    Chain *next;
}*Head[200001],*Cp[200001];


inline void Add(int u,int v)
{
    Chain *tp=new Chain;tp->next=Head[u];tp->u=v;Head[u]=tp;tp->Check=false;
}
inline void Add2(int u,int v)
{
    Chain *tp=new Chain;tp->next=Cp[u];tp->u=v;Cp[u]=tp;tp->Check=false;
}
bool Check[200001];
int F[200001][21],f[200001],Dep[200001];
inline int LCA(int a,int b)
{
    if(a==0||b==0)return a+b;
    int j;
    while(Dep[a]^Dep[b])
    {
        if(Dep[a]<Dep[b])swap(a,b);
        for(j=0;Dep[F[a][j+1]]>Dep[b];j++);
        a=F[a][j];
    }
    while(a^b)
    {
        for(j=0;F[a][j+1]^F[b][j+1];j++);
        a=F[a][j],b=F[b][j];
    }
    return a;
}

inline void DFS(int u)
{
    Check[u]=true;
    for(Chain *tp=Head[u];tp;tp=tp->next)
      if(!Check[tp->u])
       f[tp->u]=u,F[tp->u][0]=0,Dep[tp->u]=Dep[u]+1,DFS(tp->u),tp->Check=true;
}
int Du[200001];
bool Done[200001];
queue<int>Q;
inline void Cl(int x)
{
    Dep[x]=Dep[F[x][0]]+1;
for(int j=1;j<=20;j++)F[x][j]=F[F[x][j-1]][j-1];}

int Cu[200001],Dgr[200001];
int main()
{
    int n,m;read(n);m=n+1;
    for(int i=1;i<=n;i++)
     {
        while(true)
         {
            int j;
           read(j);
           if(!j)break;
           Du[i]++;
           Add(j,i);Add2(i,j);
           Cu[j]++;
         }
     }
    for(int i=1;i<=n;i++)
     if(Du[i]==0)Add(m,i),Add2(i,m),Cu[m]++,Du[i]++;
    DFS(m);
    F[m][0]=m;
    Cl(m);
    f[m]=m;
    Q.push(m);
    int sp,t=0;
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        Cl(u);
        for(Chain *tp=Head[u];tp;tp=tp->next)
         {
            if(tp->u==31)
               u++,u--;
           sp=LCA(u,F[tp->u][0]);
           F[tp->u][0]=sp;
//         Cl(F[tp->u][0]);
           Du[tp->u]--;
           if(!Du[tp->u])Q.push(tp->u);
        } 
    }
    for(int i=1;i<=n;i++)
        if(!Cu[i])Q.push(i);

    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        for(Chain *tp=Cp[u];tp;tp=tp->next)
         {
           Cu[tp->u]--;
           if(!Cu[tp->u])
           Q.push(tp->u);
         }
        Dgr[F[u][0]]+=Dgr[u]+1;

    }
    for(int i=1;i<=n;i++)
      printf("%d\n",Dgr[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值