链接:http://poj.org/problem?id=1182
参考大神文章:http://blog.csdn.net/niushuai666/article/details/6981689
并查集,不是一般的并查集,在父亲和儿子之间加了一层关系,1(同类),2(前者吃后者),这就比较尴尬了
用结构体来替换一般并查集的father数组,如
struct node { int father; int relation; } s[50002];初始化结构体
for(int i=0; i<=n; i++) { s[i].father=i; //开始是父节点为本身 s[i].relation=0; //与自己没什么关系,置零 }先排除题目中的2、3两种情况,直接判其为假:
1)当前的话中X或Y比N大,即x>n || y>n
2) 自己吃自己,即d==2 && x==y
之后查找父节点,比较重要的是更新关系域(s[i].relation)
再放一遍大神的文章:http://blog.csdn.net/niushuai666/article/details/6981689
其中的两个公式只看懂了”%3“是什么意思,我就不一本道了
还有:不需要写循环输入,写了WA;cin,cout超时
做的比较懵,还需要再理解一下(敬请指导)
#include <cstdio> using namespace std; struct node { int father; int relation; } s[50002]; int find(int n) { if(s[n].father==n) return n; int t=s[n].father; s[n].father=find(t); s[n].relation=(s[n].relation + s[t].relation)%3; return s[n].father; } int main() { int n,k; scanf("%d %d",&n,&k); int d,x,y,sum=0; for(int i=0; i<=n; i++) { s[i].father=i; s[i].relation=0; } while(k--) { scanf("%d %d %d",&d,&x,&y); if(x>n || y>n) { sum++; continue; } if(d==2 && x==y) { sum++; continue; } int rootx=find(x); int rooty=find(y); if(rootx!=rooty) { s[rooty].father=rootx; s[rooty].relation=(3+(d-1)+s[x].relation-s[y].relation)%3; } else { if(d==1 && s[x].relation!=s[y].relation) { sum++; continue; } if(d==2 && ((3-s[x].relation+s[y].relation)%3!=(d-1))) { sum++; continue; } } } printf("%d\n",sum); return 0; }