并查集
K - How Many Tables
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.
InputThe input starts with an integer T(1<=T<=25) which indicate the number of test cases. Then T test cases follow. Each test case starts with two integers N and M(1<=N,M<=1000). N indicates the number of friends, the friends are marked from 1 to N. Then M lines follow. Each line consists of two integers A and B(A!=B), that means friend A and friend B know each other. There will be a blank line between two cases. 
OutputFor each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks. 
Sample Input
2 5 3 1 2 2 3 4 5 5 1 2 5
Sample Output
2 4
这个题目非常明显用并查集做!!!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn=1010;
int f[maxn];
bool vis[maxn];
void init(int n)
{
	for(int i=1;i<=n;i++) f[i]=i;
}
int fi(int x)
{
	return f[x]==x? x: f[x]=fi(f[x]);
}
void unit(int a,int b)
{
	int t1=fi(a);
	int t2=fi(b);
	if(t1==t2) return ;
	f[t1]=t2;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m,cnt=0;
		memset(vis,0,sizeof(vis));
		scanf("%d%d",&n,&m);
		init(n);
		for(int i=1;i<=m;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			unit(a,b);
		}
		for(int i=1;i<=n;i++) f[i]=fi(i);
		for(int i=1;i<=n;i++) 
		{
			if(vis[f[i]]) continue;
		//	printf("aa %d\n",f[i]);
			vis[f[i]]=1;
			cnt++;
		}
		printf("%d\n",cnt);
	}
}
L - 畅通工程
Input测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 
注意:两个城市之间可以有多条道路相通,也就是说 
3 3 
1 2 
1 2 
2 1 
这种输入也是合法的 
当N为0时,输入结束,该用例不被处理。 
Output对每个测试用例,在1行里输出最少还需要建设的道路数目。 
Sample Input
4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
Sample Output
1
0
2
998
        
 
Huge input, scanf is recommended.
Hint
Hint
        
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn=1010;
int f[maxn],high[maxn];
void init(int n)
{
	for(int i=1;i<=n;i++) f[i]=i;
}
int findd(int x)
{
	return f[x]==x? x : f[x]=findd(f[x]);
}
void unionn(int a,int b)
{
	int t1=findd(a);
	int t2=findd(b);
	if(t1==t2) return ;
	if(high[t2]>high[t1]) f[t1]=t2;
	else 
	{
        f[t2]=t1;
		if(high[t1]==high[t2]) high[t1]++;		
	}
}
int main()
{
	int n,m;
	while(1)
	{
		memset(high,0,sizeof(high));
		scanf("%d",&n);
		if(n==0) break;
		scanf("%d",&m);
		if(m==0) 
		{
			printf("%d\n",n-1);
			continue;
		}
		if(n==1)
		{
			printf("0\n");
			continue;
		}
		init(n);
		int a,b,cnt=0;
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&a,&b);
			unionn(a,b);
		}
		for(int i=1;i<=n;i++)
		{
			if(f[i]==i) cnt++;
		}
		printf("%d\n",cnt-1);
	}
	return 0;
}
并查集其实很简单,学一下应该就可以学会了,接下来推荐一篇博文,写的很好,还有一个大佬的视频,这个是最基础的,当然除此之外,还有种类并查集和带权并查集。
博文:https://blog.csdn.net/Hacker_ZhiDian/article/details/60965556
视频:https://www.bilibili.com/video/av7657321
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号