poj1182 食物链

题意:

三类动物A、B、C,A吃B,B吃C,C吃A。
给出K句话来描述N个动物(各属于A、B、C三类之一)之间的关系,格式及意义如下:
1 X Y:表示X与Y是同类;
2 X Y:表示X吃Y。
K句话中有真话有假话,当一句话满足下列三条之一时,这句话就是假话,否则就是真话。1)当前的话与前面的某些真的话冲突,就是假话;2)当前的话中X或Y比N大,就是假话;3)当前的话表示X吃X,就是假话。
求假话的总数。

输入:
第一行是两个整数N和K,以一个空格分隔。以下K行每行是三个正整数D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。若D=1,则表示X和Y是同类。若D=2,则表示X吃Y。
输出:
只有一个整数,表示假话的数目。
约束条件:
1 <= N <= 50000,0 <= K <= 100000。

思路:

并查集中的元素并不是动物,而是每只动物属于某种类别的信息。

具体来说,对于每只动物i创建i-A,i-B,i-C,并用这3*N个元素建立并查集。i-x表示“i属于种类x”。并查集里的每一个组内表示所有元素代表的情况同时发生或不发生。

对于x和y属于同一种类这种信息,合并x-A和y-A,x-B和y-B,x-C和y-C;

对于x吃y这种信息,合并x-A和y-B,x-B和y-C,x-C和y-A。

合并之前检查是否矛盾并计数即可。

实现:

 1 #include <iostream>
 2 #include <cstdio>
 3 #define MAXN 50000
 4 using namespace std;
 5 int a[MAXN + 10];
 6 int par[3 * MAXN + 10];
 7 int ran[3 * MAXN + 10];
 8 void init(int n)
 9 {
10     for (int i = 0; i <= n; i++)
11     {
12         par[i] = i;
13         ran[i] = 0;
14     }
15 }
16 int find(int x)
17 {
18     if (x == par[x])
19         return x;
20     return par[x] = find(par[x]);
21 }
22 void unite(int x, int y)
23 {
24     x = find(x);
25     y = find(y);
26     if (x == y)
27     {
28         return;
29     }
30     if (ran[x] < ran[y])
31     {
32         par[x] = y;
33     }
34     else
35     {
36         par[y] = x;
37         if (ran[x] == ran[y])
38         {
39             ran[x]++;
40         }
41     }
42 }
43 bool same(int x, int y)
44 {
45     return find(x) == find(y);
46 }
47 int main()
48 {
49     int n, k, t, x, y;
50     cin >> n >> k;
51     int cnt = 0;
52     init(3 * n);
53     for (int i = 0; i < k; i++)
54     {
55         scanf("%d %d %d", &t, &x, &y);
56         if (x <= 0 || x > n || y <= 0 || y > n)
57         {
58             cnt++;
59             continue;
60         }
61         x--;
62         y--;
63         if (t == 1)
64         {
65             if (same(x + n, y + 2 * n) || same(x + n, y))
66             {
67                 cnt++;
68             }
69             else
70             {
71                 unite(x, y);
72                 unite(x + n, y + n);
73                 unite(x + 2 * n, y + 2 * n);
74             }
75         }
76         else
77         {
78             if (same(x + n, y) || same(x + 2 * n, y + 2 * n))
79             {
80                 cnt++;
81             }
82             else
83             {
84                 unite(x, y + n);
85                 unite(x + n, y + 2 * n);
86                 unite(x + 2 * n, y);
87             }
88         }
89     }
90     cout << cnt << endl;
91     return 0;
92 }

 

转载于:https://www.cnblogs.com/wangyiming/p/6357902.html

内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值