#惊奇建模<主仆见证了 Hobo 的离别>
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 }
抽象建模很需要学