Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 60260 | Accepted: 17665 |
Description
Input
Output
Sample Input
100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5
Sample Output
3
Source
感觉并查集很高大上的样子啊 但其实我们自己想的话是很简单的 其实主要处理好父子节点的关系进而推出子节点与根节点的关系进行路径压缩,就算是解决问题了……
那时的poj,还是中文的……感动……
代码在这:
#include <iostream> #include <cstdio> using namespace std; int father[50001],rank[50001]; int n,k; int flag=0; void init(int n) //初始化 { for(int i=1;i<=n;++i) { father[i]=i; rank[i]=0; } } int getanc(int x) { if(x==father[x]) return x; //本身 else { int fx=getanc(father[x]); // 寻找此点的根节点 rank[x]=(rank[x]+rank[father[x]])%3;//判断此点与根节点吃与被吃的关系 father[x]=fx;//将此点父节点改为根节点->路径压缩 } return father[x]; } bool union_set(int x,int y,int d) { int fx=getanc(x); //两数根节点 int fy=getanc(y); if(fx==fy) { if((rank[y]-rank[x]+3)%3==(d-1)) return true;//若两数根节点相同且对应关系正确,真话 else return false; } father[fy]=fx; rank[fy]=((3-rank[y])+(rank[x])+(d-1))%3;//rank[fy]归纳,两数根节点对应关系,分三部分 return true; } int d,x,y; int main() { scanf("%d%d",&n,&k); init(n); flag=0; for(int i=0;i<k;++i) { scanf("%d%d%d",&d,&x,&y); if((d==2&&x==y)||x>n||y>n) {flag++;continue;} else if(!union_set(x,y,d)) flag++; } printf("%d\n",flag); return 0; }