1 新元件的编号等于融合之前元件的总个数加一。当然,参与融合的 K个元件融合之后依然存在,并且每个元件至多参与一次融合。 2 由于元件的容量有限,Eddie 没有能力唤醒 Hobo 全部的回忆,所以他会用下列两种方式来融合元件: 3 4 集合的交:一段记忆存储在新的元件中,当且仅当这段记忆在参与融合的K 个元件中都有储存。 5 集合的并:一段记忆存储在新的元件中,当且仅当这段记忆在参与融合的至少一个元件中有储存。
考试没留时间,(留时间估计也想不粗来,雾),我们考虑建图,一条有向边a指向b的意义是a包含b的内容,但考虑K==1的情况,实质上是新点和所给点的内容完全相同,那么建双向边。每次用dfs判断是否Y能到X。至于复杂度,(首先数据很水),其次,每个点只融合一次,两两造点的话,这个图的深度也很小。
1 #include<cstdio> 2 #include<iostream> 3 #define MAXN 251000 4 using namespace std; 5 int N,M; 6 struct rr{ 7 int nt,to; 8 }bl[MAXN*30];int hd[MAXN*3],itot; 9 void add(int x,int y){ 10 bl[++itot].to=y; 11 bl[itot].nt=hd[x]; 12 hd[x]=itot; 13 } 14 bool dfs(int u,int fa,int md){ 15 if(u==md)return true; 16 for(int i=hd[u];i;i=bl[i].nt) 17 if(bl[i].to!=fa) 18 if(dfs(bl[i].to,u,md))return true; 19 return false; 20 } 21 int main(){ 22 //freopen("da.in","r",stdin); 23 scanf("%d%d",&N,&M); 24 int knd,opt,K,X,Y,rt; 25 int num=N; 26 for(int i=1;i<=M;++i){ 27 scanf("%d",&knd); 28 if(knd){ 29 scanf("%d%d",&X,&Y); 30 printf("%d\n",dfs(Y,0,X)); 31 } 32 else{ 33 scanf("%d",&opt); 34 if(opt){ 35 scanf("%d",&K);++num; 36 for(int i=1;i<=K;++i)scanf("%d",&rt),add(num,rt); 37 if(K==1)add(rt,num); 38 } 39 else{ 40 scanf("%d",&K);++num; 41 for(int i=1;i<=K;++i)scanf("%d",&rt),add(rt,num); 42 if(K==1)add(num,rt); 43 } 44 } 45 } 46 return 0; 47 }
抽象建模很需要学
原文:https://www.cnblogs.com/2018hzoicyf/p/11379695.html