这题不错,想法题。我开始的思路是新增加[n+1,2*n]这个区间的点拿来作为分类的标记,x,y同类则Union(x,y),x吃y则Union(x,n+cnt++),Union(y,n+cnt++),这样处理起来稍微麻烦,而且无法解决大类的合并。然后换一个思路,把合并看成是x,y确定关系了,在同一个集合就表示两者关系确定,然后具体是什么关系新加一个域来表示,这个域存的是当前节点和父节点的关系,并查的时候注意维护这个域就好了。所以第一类假话当然是在两者关系确定但是和输入的关系不符合的情况。
#include <algorithm> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <map> #include <set> #include <list> #include <stack> #include <queue> #include <deque> #include <vector> #include <string> #include <bitset> #include <memory> #include <complex> #include <numeric> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <time.h> #include <ctype.h> #include <locale.h> using namespace std; #pragma pack(4) const double eps = 1e-8; const double pi = acos(-1.0); const int inf = 0x7f7f7f7f; #define loop(a,n) \ for(int i=0;n>i;i++) \ cout<<a[i]<<(i!=n-1?' ':'\n') #define loop2(a,n,m) \ for(int i=0;n>i;i++) \ for(int j=0;m>j;j++) \ cout<<a[i][j]<<(j!=m-1?' ':'\n') #define at(a,i) ((a)&(1<<(i))) #define nt(a,i) ((a)^(1<<(i))) #define set1(a,i) ((a)|(1<<(i))) #define set0(a,i) ((a)&(~(1<<(i)))) #define cmp(a,b) (fabs((a)-(b))<eps?0:(((a)-(b))>eps?+1:-1)) #define lmax(a,b) ((a)>(b)?(a):(b)) #define lmin(a,b) ((a)<(b)?(a):(b)) #define fmax(a,b) (cmp(a,b)>0?(a):(b)) #define fmin(a,b) (cmp(a,b)<0?(a):(b)) const int MAXV = 50002; class UFS { private: int Pa[MAXV],Ki[MAXV]; public: void clear(int l,int r) { for(int i=l;i<=r;i++) { Pa[i]=i; Ki[i]=0; } } int operator [] (int i) { return Ki[i]; } int Find(int u) { if(Pa[u]!=u) { int v=Pa[u]; int w=Find(Pa[u]); Pa[u]=w; Ki[u]=(Ki[u]+Ki[v]+3)%3; return w; } else return u; } void Union(int u,int v,int k) { int uu=Find(u); int vv=Find(v); Pa[uu]=vv; Ki[uu]=(Ki[v]-Ki[u]-k+3)%3; } }ufs; int n,k,x,y,o; int main() { #ifndef ONLINE_JUDGE freopen("食物链.txt","r",stdin); #else #endif scanf("%d %d",&n,&k); int cnt=0; ufs.clear(1,n); while(k--) { scanf("%d %d %d",&o,&x,&y); if(x>n||y>n) cnt++; else if(o==2&&x==y) cnt++; else if(o==1&&ufs.Find(x)==ufs.Find(y)&&ufs[x]!=ufs[y]) cnt++; else if(o==2&&ufs.Find(x)==ufs.Find(y)&&(ufs[x]+1)%3!=ufs[y]) cnt++; else ufs.Union(x,y,o-1); } printf("%d\n",cnt); return 0; }