标签:open 两种 img 熬夜 同余 递归 std 有一个 wing
题目:
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。
A吃B, B吃C,C吃A。
现有N个动物,以1-N编号。
每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
有人用两种说法对这N个动物所构成的食物链关系进行描述:
第一种说法是”1 X Y”,表示X和Y是同类。
第二种说法是”2 X Y”,表示X吃Y。
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。
当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。
你的任务是根据给定的N和K句话,输出假话的总数。
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
只有一个整数,表示假话的数目。
1≤N≤500001≤N≤50000,
0≤K≤1000000≤K≤100000
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
3
刚开始看的时候觉得并查集好像写不了,就是自己憨憨了,实际上就是取模分为三类,这就是通过这些东西的传递性来确定到祖宗的距离,距离可以分为三类(0,1,2)在取模的情况下
这道题目重点就是想清楚这个取模分类的思路
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <map> 7 #include <vector> 8 #include <set> 9 #include <stack> 10 11 using namespace std; 12 typedef long long ll; 13 14 const int N = 5e4 +10; 15 int p[N],d[N]; 16 int find(int x) 17 { 18 if(p[x]!=x) 19 { 20 int t = find(p[x]); 21 d[x] += d[p[x]];//从递归的最低层开始更新距离 22 p[x] = t;//路径压缩 23 } 24 return p[x]; 25 } 26 int main() 27 { 28 int n,k; 29 cin >> n >> k; 30 for(int i=0;i<=n;i++) 31 { 32 p[i]=i; 33 } 34 int a,x,y; 35 int cun=0; 36 while(k--) 37 { 38 scanf("%d%d%d",&a,&x,&y); 39 if(x>n||y>n) 40 { 41 cun++; 42 } 43 else{ 44 if(a==1) 45 { 46 int px = find(x); 47 int py = find(y); 48 if(px==py&&(d[x] - d[y])%3)cun++;//判断不是同余的距离就不是同一类 49 else if(px != py) 50 { 51 p[px] = py; 52 d[px] = (d[y] - d[x])%3; 53 } 54 } 55 else { 56 int px = find(x); 57 int py = find(y); 58 if(px==py&&(d[x] - d[y] -1)%3)cun++;//x吃y,就是在取模的情况下 (d[x] - d[y])%3 =1 59 else if(px != py) 60 { 61 p[px] = py; 62 d[px] = (d[y] + 1 - d[x])%3; 63 } 64 } 65 } 66 } 67 cout << cun <<endl; 68 }
emmm,今天是20200202,是一个比较特殊的日子,确定了今天是自己一个人熬夜补题的日子,自己自律,加油,别再不被重视了,最后一年了,再不努力就再也没有机会了。
标签:open 两种 img 熬夜 同余 递归 std 有一个 wing
原文地址:https://www.cnblogs.com/wangzhe52xia/p/12253746.html