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
",f[i]);
vis[f[i]]=1;
cnt++;
}
printf("%d
",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-1);
continue;
}
if(n==1)
{
printf("0
");
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
",cnt-1);
}
return 0;
}
并查集其实很简单,学一下应该就可以学会了,接下来推荐一篇博文,写的很好,还有一个大佬的视频,这个是最基础的,当然除此之外,还有种类并查集和带权并查集。
博文:https://blog.csdn.net/Hacker_ZhiDian/article/details/60965556