Description
One important rule for this problem is that if I tell you A knows B, and B knows C, that means A, B, C know each other, so they can stay in one table.
For example: If I tell you A knows B, B knows C, and D knows E, so A, B, C can stay in one table, and D, E have to stay in the other one. So Ignatius needs 2 tables at least.
Input
Output
Sample Input
Sample Output
加入了壓縮路徑
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
using namespace std;
int m,n,parent[20000];
void UFset()//初始化
{
for(int i=1;i<=m;i++)
parent[i]=-1;
}
int Find(int x)
{
int s;//查找位置,一直找到parent[s]爲負數爲止
for(s=x;parent[s]>=0;s=parent[s]);
while(s!=x)
{
int tmp=parent[x];//優化方案,壓縮路徑,更新子節點
parent[x]=s;
x=tmp;
}
return s;
}
void Union( int R1,int R2 )
{
int r1=Find(R1),r2=Find(R2);
int tmp=parent[r1]+parent[r2];//兩個集合結點個數之和(負數)
if(parent[r1]>parent[r2])//優化方案--加權法則
{
parent[r1]=r2;//根節點r1所在的樹作爲r2的子樹
parent[r2]=tmp;
}
else
{
parent[r2]=r1;//<span style="font-family: Arial, Helvetica, sans-serif;">//根節點r2所在的樹作爲r1的子樹</span>
parent[r1]=tmp;
}
}
int main()
{
int N;
scanf("%d",&N);
while(N--)
{
scanf("%d%d",&m,&n);
UFset();
int a,b;
for(int i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
if(Find(a) != Find(b))//這裏要進行判斷父節點不等,才經行合併
Union(a,b);
}
int num=0;
for(int i=1;i<=m;i++)
{
if(parent[i]<0)
num++;
}
printf("%d\n",num);
}
return 0;
}