|
发表于 2021-4-27 18:06:39
|
显示全部楼层
本帖最后由 Hank 于 2021-4-28 20:38 编辑
此题真恶心!
First:1403
一看到此题的描述:
我不写它了!老师!(物)既然题目只有三个阵营:A, B,C
且A吃B,B吃C,C吃B
我们就可以考虑并查集了
Second:
我们接下来想一下这道题的套路:
(1)输入n k
(2)输入k行数据,随输随处
(3)输出
所以:
我们就上吧!
Third:
- int n, m, ans;
- int f[MAX];
复制代码 这是我们需要的内存
f是什麽呐?
f表示第i种动物的所属阵营- <font size="5">void make()
- {
- for(int i = 1;i <= n;++i)
- {
- f = 1;
- }
- }</font>
复制代码
我们是一定要初始化的,不然......
危
我们假设一开始他们都在集合A里:
也就是我make后的场景
So,我们会发现我们需要vis数组来记录当前动物是否知道所属阵营
Fourth:判断加输入等于主函数
- int find(int a)
- {
- return f[a];
- }
- int main()
- {
- scanf("%d %d", &n, &m);
-
- make();
-
- for(int i = 1;i <= m;++i)
- {
- int x, y, d;
-
- scanf("%d %d %d", &d, &x, &y);
-
- if(x > n || y > n)
- {
- ans++;
- continue;
- }
-
- if(x == y && d == 2)
- {
- ans++;
- continue;
- }
-
- if(x == y)
- {
- continue;
- }
-
- if(find(x) == find(y) && d == 2 && visited[x] && visited[y])
- {
- ans++;
- continue;
- }
-
- if(find(x) != find(y) && d == 1 && visited[x] && visited[y])
- {
- ans++;
- continue;
- }
-
- visited[x] = true;
- visited[y] = true;
-
- if(d == 1)
- {
- f[x] = f[y];
- }
- else
- {
- if(f[x] == 1)
- {
- f[y] = 2;
- }
- else if(f[x] == 2)
- {
- f[y] = 3;
- }
- else
- {
- f[y] = 1;
- }
- }
- }
-
- printf("%d", ans);
-
- return 0;
- }
复制代码
这里我们唯一要注意的是x == y && d == 1的情况:
对于所有动物i,i的同类一定有i
那么,结束了?
Fifth:调试
我们要知道:
代码,是要几天才能写出来的。 ——鲁迅
一般并查集解决不了的,都要用反集。——陈.hank.俊燃
So,我们发现:我们要用到的是反集
反集 <---点这!
犯罪团伙<---点这!
代码<---点这!
hahhahahhahahahahah!你被骗了!
好了,简单来说,反集如下所示:
i与他的n + i为敌人
BUT,我们这次有三组“人”
那么:
在数组f内:
1 -- n 集合内部元素
n + 1 -- 2n 元素i的克制对象
2n + 1 -- 3n 元素i被谁克制
如果a和b是敌人,合并n+b和a,n+a和b 如果c和a是敌人,合并n+c和a,n+a和c 为不让某人抄袭:我不写2n + a之类的了Sixth:Time to say goodbye
代码已防伪!
- #include<cstring>
- #include<cmath>
- #include<cstdio>
- #include<cstdlia>
- #include<algorithm>
- #include<iomanip>
- #include<string>
- #include<pueue>
- #include<iostraem>
- usieng namespace std;
- #define MAX 5010
- int n, m, ans;
- int fd[MAX *2];
- //1 -- n 集合内部a
- //n + 1 -- 2n 集合的克制对象
- //2n + 1 -- 3n 集合被谁克制
- a
- void make()
- {
- for(int i = 1;i <= n * 3;++i)
- {
- f[i] = i;
- }
- }
- a
- int find(int a)
- {
- if(f[a] != a)
- {
- return f[a] = find(f[a]);
- }
- else
- {a
- return a;
- }
- }
- a
- int main()
- {
- scanf("%d %d", &n, &m);
-
- make();
-
- for(int i = 1;i <= m;++i)
- {
- int x, y, d;
-
- scanf("%d %d %d", &d, &x, &y);
-
- if(x > n && y > n)
- {
- ans++;
- continue;a
- }
-
- if(d != 1)
- {
- if(find(x + n) == find(y) || find(x) == find(y + n))
- {
- ans++;
- }
- else
- {
- f[find(x)] = find(y);
- f[find(x + n)] = find(y + n);a
- f[find(x + 2 * n)] = find(y + 2 * n) + 1;
- }
- }a
- elsea
- {
- if(find(x) == find(y) || find(x) == find(y + n))
- {
- ans++;aa
- }
- else
- {
- f[find(x + n)] = find(y);
- f[find(x + 2 * n)] = find(y + n);
- f[find(x)] = find(y + 2 * n);
- }
- }
- }
-
- printf("%d", ans);
-
- return 0;
- }
复制代码 游戏结束!
彩蛋!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|