• ACM-POJ-No. 1182-食物链-并查集


    题目

    在这里插入图片描述

    分析

    给每个动物赋予三个节点(n,2n,3n),那就将一个动物扩展到了3个(x——>x_A 、x_B
    x_C),这样就将并查集的节点数量扩展到3n,用并查集维护这 3n 个节点的信息。

    (如果不太了解并查集的代码,可以参考下我的另外一篇博文:并查集简单介绍

    那么把题目中的给的 K 条信息转换一下(且用并查集维护这个关系):

    1. 如果 x 和 y 两个动物是同类:
      (1)x_a 和 y_a 是同类;合并 x_a 和 y_a 。
      (2)x_b 和 y_b 是同类;合并 x_b 和 y_b 。
      (3)x_c 和 y_c 是同类;合并 x_c 和 y_c 。
    2. 如果 x 吃 y 说明:
      (1)x_a 吃 y_b;合并 x_a 和 y_b。
      (2)x_b 吃 y_c; 合并 x_a 和 y_b。
      (3)x_c 吃 y_a;合并 x_a 和 y_b。
    3. 如果 x 和 y 一定不是同类,说明存在以下情况:
      (1)要么 x 吃 y
      (eg:x_a 吃 y_b , 则x_a 和 y_b 在一个集合里…)
      (2)要么 y 吃 x
      (eg:y_a 吃 x_b ,则y_a 和 x_b 在一个集合里…)
    4. 如果 x 一定不吃 y ,说明存在以下情况:
      (1)要么 x 和 y 同类
      (eg:x_a 和 y_a 是同类,则x_a 和 y_a 在一个集合里…)
      (2)要么 y 吃 x
      (eg:y_a 吃 x_b ,则y_a 和 x_b 在一个集合里…)

    坑:注意这里的输入用scanf 或者 用cin加上std::ios::sync_with_stdio(false); 不然会超时,通不过。

    AC代码

    #include
    #define Max_K 100000+5
    #define Max_N 150000+5
    using namespace std;
    int T[Max_K],X[Max_K],Y[Max_K];//记录输入的K条信息
    int N,K;//N个动物 K条信息
    
    int par[Max_N];//记录每个结点i的父亲 ;每个动物有3个结点,表示ABC三类,x,x+N,x+2*N分别代表x-A x-B x-C
    int rank[Max_N];//树的高度
    
    void init(int n) { //初始化
    	for(int i=0; i<n; i++) {
    		par[i]=i;
    		rank[i]=0;
    	}
    }
    
    int find(int x) {//查找根节点
    	if(par[x]==x)
    		return x;
    	return par[x]=find(par[x]);
    }
    
    void unite(int x,int y) {//合并
    	x=find(x);
    	y=find(y);
    	if(x==y)
    		return ;
    	if(rank[x]<rank[y])
    		par[x]=y;
    	else {
    		par[y]=x;
    		if(rank[x]==rank[y])
    			rank[x]++;
    	}
    }
    
    bool same(int x,int y) {//判断是否同一类
    	return find(x)==find(y);
    }
    
    void solve() {
    	init(N*3);//初始化合并集,每个动物有3个结点,每个动物都有属于ABC三类,x,x+N,x+2*N分别代表x-A x-B x-C
    	int ans=0;
    	for(int i=0; i<K; i++) { //循环开始判断K条信息的正确与否
    		int t=T[i];
    		int x=X[i]-1,y=Y[i]-1;//把输入的动物编号改为0~N-1
    
    		if(x<0 ||N<=x||y<0||N<=y) { //该动物编号 不合法
    			ans++;
    			continue;
    		}
    		if(t==1) { //x y是同类?
    			if(same(x,y+N)||same(x,y+2*N)) { //如果x吃y 或者y吃x 说明是假话
    				ans++;
    			} else { //同类合并:每个x_ABC 和y_ABC 都合并为一类
    				unite(x,y);
    				unite(x+N,y+N);
    				unite(x+N*2,y+N*2);
    			}
    		} else { //是x吃y的关系?
    			if(same(x,y)||same(x,y+2*N)) { //如果x,y是同类  或者是y吃x的关系  说明是假话
    				ans++;
    			} else {//是吃的关系,将x与y的有可能的吃的关系都合并
    				unite(x,y+N);//x_A吃y_B
    				unite(x+N,y+2*N);//x_B吃y_C
    				unite(x+N*2,y);//x_C吃y_A
    			}
    		}
    	}
    	printf("%d\n",ans);
    }
    int main() {
    	scanf("%d%d",&N,&K);// //N个动物 K条信息
    	for(int i=0; i<K; i++) {
    		scanf("%d%d%d",&T[i],&X[i],&Y[i]);
    	}
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    收获

    1. 并查集的运用。
    2. 通过扩充动物来实现更简单的维护关系。
  • 相关阅读:
    [Note]时钟门控的时序检查
    速报|StarRocks亮相云栖大会,携手阿里云EMR 打造极速数据湖分析新体验
    springboot+mybatis3.5.2动态查询某一字段在某一段时间内的统计信息(折线图)
    LDblock绘制连锁不平衡和单体型图
    vue3 ref和reactive使用watch属性的方法和区别
    Mac苹果电脑开不了机怎么办,该怎么修复
    ASF HyP3 Python接口使用教程
    划分Vlan时需要注意的问题
    预测性维护为何能够帮助企业降低设备维护成本?
    ffmpeg在windows的安装、合并、切片、.m4s、.m3u8处理
  • 原文地址:https://blog.csdn.net/qq_51219814/article/details/126917427