POJ 1308 这还算并查集吗?

这还算并查集吗?

形似。

其实就是用了父节点表示法的树和森林 这种意义上来说更像是模拟做法。

每读入一根树枝A->B, 判断A==B,如果相等,构成自环,可断定不是树。

如果已经有节点指向B了,也可断定不是树,因为树除了根节点入度为零外,其余节点入度为一。不可能有一个以上的结点指向某节点。

若非以上情况,说明这根树枝是合法的,将B节点指向A节点。

在全部数据输入完毕后。

判断所有结点的根结点是否相同,如果相同则是树。

寻找根结点的操作室一直沿着from成员向上追溯。

这里要想办法判断出成环的情况,因为如果成环,寻找根结点的操作将无法返回。

解决的办法是,规定一个追溯次数1000,若大于1000仍未找到,认为成环。

代码如下:

#include <iostream> using namespace std; struct{ int from; int used; }theNode[1005]; void MakeSet() { for (int i = 1;i <= 1000;i++) { theNode[i].from=0; theNode[i].used=0; } } void Add(int NodeX,int NodeY) { theNode[NodeX].used = 1; theNode[NodeY].used = 1; theNode[NodeY].from = NodeX; } int FindRoot(int NodeToFind,int FindTimes) { if(FindTimes>1000) //it is a loop return -5; if(theNode[NodeToFind].from==0) return NodeToFind; return FindRoot(theNode[NodeToFind].from,FindTimes+1); } int main() { int Case=0; while (++Case) { MakeSet(); bool IsATree=true; int a,b; while (cin>>a>>b&&a>0) { if(a==b) IsATree=false; else if(theNode[b].from==0) Add(a,b); else IsATree=false; } if (a==0) { if (!IsATree) { cout<<"Case "<<Case<<" is not a tree."<<endl; } else { int root=0,times=0; for (int i = 1;i < 1000;i++) { if (theNode[i].used==1) { if(times==0) root=FindRoot(i,1); else if(root!=FindRoot(i,1)||FindRoot(i,1)<0||root<0) { IsATree=false; break; } times++; } } if (IsATree) { cout<<"Case "<<Case<<" is a tree."<<endl; } else { cout<<"Case "<<Case<<" is not a tree."<<endl; } } } else break; } }

你可能感兴趣的:(POJ 1308 这还算并查集吗?)