并查集:判断是否属于同一棵树
数组:记录入度
#include <cstdio>
#include <cstdlib>
#include <set>
#include <iterator>
#define MAXN 10001
using namespace std;
set<int> st;
set<int>::iterator it;
int father[MAXN];
int degree[MAXN];//入度
void makeSet(){
for (int i=1; i<MAXN; i++) {
father[i]=i;
degree[i]=0;
}
}
int findSet(int x){
return x==father[x]?x:father[x]=findSet(father[x]);
/* if (x!=father[x]) {
father[x]=findSet(father[x]);//路径压缩
}
return father[x];*/
}
void unionSet(int x,int y){
int fx=findSet(x);
int fy=findSet(y);
father[fy]=fx;
}
int main(){
bool fail;
int k=1;
int a,b;
while (scanf("%d%d",&a,&b)&&(a!=-1&&b!=-1)) {
if (a==0&&b==0) {//空树
printf("Case %d is a tree.\n",k++);
continue;
}
st.clear();//清空
st.insert(a);
st.insert(b);
makeSet();//初始化
unionSet(a, b);
++degree[b];//入度++
while (scanf("%d%d",&a,&b)&&(a&&b)) {//a,b!=0
st.insert(a);
st.insert(b);
unionSet(a, b);
++degree[b];
}
int fs=findSet(father[*st.begin()]);
int zeroCnt=0;//统计有多少个入度为0的节点
fail=false;
for (it=st.begin(); it!=st.end(); ++it) {
if (fs!=findSet(father[*it])) {//树中节点的祖先都一样,否则不是树
fail=true;
break;
}
if (degree[*it]>1) {//入度>1不是树
fail=true;
break;
}
if (degree[*it]==0) {//统计根
++zeroCnt;
}
}
printf("Case %d ",k++);
if (fail||zeroCnt!=1) {//根不是一个
printf("is not a tree.\n");
}else{
printf("is a tree.\n");
}
}
return 0;
}
POJ1611
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXN=30001;
int fa[MAXN];//父节点
int ran[MAXN];
int num[MAXN];//节点数
void makeSet(int n){
for (int i=0; i<n; i++){
fa[i]=i;
num[i]=1;
}
}
int findSet(int x){
int r=x;
while (fa[r]!=r) {//find the root
r=fa[r];
}
int t=x;
while (x!=r) {//compress
t=fa[x];
fa[x]=r;
x=t;
}
return r;
}
void unionSet(int x,int y){
int fx=findSet(x);
int fy=findSet(y);
if (num[fx]>num[fy]) {
fa[fy]=fx;
num[fx]+=num[fy];
}else{
fa[fx]=fy;
num[fy]+=num[fx];
}
}
int main(){
int m,n;
while (scanf("%d %d",&n,&m)) {
if (m==0&&n==0) {
break;
}
if (m==0) {//group is 0
printf("1\n");
continue;
}
makeSet(n);//n student
int t;
for (int i=0; i<m; i++) {
scanf("%d",&t);
int ni,nj;
scanf("%d",&ni);
for (int j=1; j<t; j++) {
scanf("%d",&nj);
if (findSet(ni)!=findSet(nj)) {
unionSet(ni, nj);
}
ni=nj;
}
}
int res=findSet(0);
printf("%d\n",num[res]);
}
return 0;
}
POJ2524
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXN=50001;
int fa[MAXN];
int ran[MAXN];
int res;
void makeSet(int n){
for (int i=0; i<n; i++) {
fa[i]=i;
ran[i]=1;
}
}
int findSet(int x){
int r=x;
while (fa[r]!=r){//find the root
r=fa[r];
}
int t=x;
while (x!=r) {//compress
t=fa[x];
fa[x]=r;
x=t;
}
return r;
}
void unionSet(int x,int y){
int fx=findSet(x);
int fy=findSet(y);
if (ran[x]>ran[y]) {
fa[fy]=fx;
}else{
fa[fx]=fy;
if (ran[fx]==ran[fy]) {
ran[fy]++;
}
}
res--;//kind-1
}
int main(){
int m,n,k=1;
while (scanf("%d%d",&n,&m)) {
if (n==0&&m==0) {
break;
}
makeSet(n);
res=n;//n kind
int x,y;
for (int i=0; i<m; i++) {
scanf("%d%d",&x,&y);
if (findSet(x)!=findSet(y)) {
unionSet(x, y);
}
}
printf("Case %d: %d\n",k,res);
k++;
}
return 0;
}
POJ1182
使用带权值的并查集
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int LYD=50010;//animal number upper
struct Animal{
int num;
int parent;
int relation;//relationship with father node
};
Animal ani[LYD];
int res=0;
int findParent(Animal *node){
int tmp;
if (node->parent==node->num) {//root
return node->parent;
}
tmp=node->parent;
//printf("Animal %d s Parent is %d\n",node->num,node->parent);
node->parent=findParent(&ani[node->parent]);
node->relation=(ani[tmp].relation+node->relation)%3;
return node->parent;
}
void UnionSet(int x,int y,int a,int b,int d){
ani[b].parent=a;
ani[b].relation=((3-ani[y].relation)+(d-1)+ani[x].relation)%3;
}
void initAnimal(int n){
for (int i=1; i<=n; i++) {
ani[i].num=i;
ani[i].parent=i;
ani[i].relation=0;
}
}
int main(){
int N,K;
int d,X,Y;
scanf("%d%d",&N,&K);
initAnimal(N);
for (int i=0; i<K; i++) {
scanf("%d%d%d",&d,&X,&Y);
if (X>N||Y>N) {//error case2
res++;
}else{
if (d==2&&X==Y) {//error case3
res++;
}else{
int a=findParent(&ani[X]);
int b=findParent(&ani[Y]);
if (a!=b) {//different set
UnionSet(X, Y, a, b, d);
}else{//same set
switch (d) {
case 1:
if (ani[X].relation!=ani[Y].relation) {
res++;
}
break;
case 2:
if (((ani[Y].relation+3-ani[X].relation)%3)!=1) {
res++;
}
break;
default:
break;
}
}
}
}
}
printf("%d\n",res);
return 0;
}