2815: [ZJOI2012]灾难
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1518 Solved: 848
[Submit][Status][Discuss]
Description
http://www.lydsy.com/JudgeOnline/upload/zjoi2012.pdf
Input
Output
Sample Input
Sample Output
HINT
Source
题面好简陋啊QAQ
抄自cydiater大神
学LCA的时候根本没意识到LCA可以有这么多玩法。
这玩意据说是个高级数据结构(支配树)的弱化版,蒟蒻没学过呀。所以出题人提出一个概念叫灾难树。
我理解的灾难树的意思实际上是属于DAG的一个子图(我不知道怎么描述,就叫子图吧!)。灾难树关于DAG有这样一个性质。就是说在DAG上删掉某一点后,如果存在一个点的入度变为0.那么这个点就删去,以此类推,而被删去的点是这个所有被迫删除的点的父亲。
上面实际上就是把题面描述了一遍QAQ。
如何根据原DAG构建灾难树呢?
首先把DAG拓扑排个序。然后逆序遍历,对于拓扑序上的每一个点。找到他所有子节点在新图上的LCA(如果不存在或者LCA就是该节点就设为0)。然后就在新图上由LCA向这个点连边。最后形成的新图就是灾难树。
其实如果偏感性的理解的话,就是如果一个点所有出边所连接的点,或者通俗点说,就是所有食物都没了,那么这个点是一定要随之被删掉的。也就是说LCA的被删去必定会导致当前节点的被删去。
#include <bits/stdc++.h> using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=700000; namespace zhangenming{ struct node{ int y;int next; }e[MAXN],E[MAXN]; int linkk[MAXN],Linkk[MAXN],n,len=0,siz[MAXN]={},cnt[MAXN]={},fa[MAXN][22]={},q[MAXN]; int dep[MAXN]={},head=0,tail=0; inline void insert(int xx,int yy){e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len;} inline void Insert(int xx,int yy){E[++len].y=yy;E[len].next=Linkk[xx];Linkk[xx]=len;} void init(){ n=read(); for(int i=1;i<=n;i++){ int yy=read();; while(yy){ insert(i,yy); cnt[yy]++; yy=read(); } } } void dfs(int node){ for(int i=Linkk[node];i;i=E[i].next){ dfs(E[i].y); siz[node]+=siz[E[i].y]; } siz[node]+=1; } void getanser(int st){ for(int i=1;i<=21;i++){ if(fa[st][i-1]!=0) fa[st][i]=fa[fa[st][i-1]][i-1]; } } int LCA(int xx,int yy){ if(xx==-1) return yy; if(dep[xx]<dep[yy]) swap(xx,yy); for(int i=20;i>=0;i--){ if(dep[xx]-(1<<i)>=dep[yy]) xx=fa[xx][i]; } if(xx==yy) return xx; for(int i=20;i>=0;i--){ if(fa[xx][i]!=fa[yy][i]&&fa[xx][i]!=0) {xx=fa[xx][i];yy=fa[yy][i];} } return fa[xx][0]; } void solve(){ for(int i=1;i<=n;i++){ if(cnt[i]==0) q[++tail]=i; } while(head<tail){ int tn=q[++head]; for(int i=linkk[tn];i;i=e[i].next){ if(--cnt[e[i].y]==0) {q[++tail]=e[i].y;dep[e[i].y]=dep[tn]+1;} } } for(int h=tail;h>0;h--){ int lca=-1;int node=q[h]; for(int i=linkk[node];i;i=e[i].next){lca=LCA(lca,e[i].y);} if(lca==node||lca==-1) lca=0; Insert(lca,node);fa[node][0]=lca;dep[node]=dep[lca]+1; getanser(node); } dfs(0); } void print(){ for(int i=1;i<=n;i++){ printf("%d ",siz[i]-1); } } } int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); using namespace zhangenming; init(); solve(); print(); return 0; }