运送物资
Time Limit: 1000MS Memory limit: 65536K
题目描述
A地区发生了洪灾,造成部分道路被毁,通信中断。为了先安顿受灾群众,政府决定利用船只向各个灾民聚集区域运送救灾物资。已知A地区共有居民居住点N个,编号为1-N,受灾后经过卫星拍摄的图片发现还有M条道路可用,并且两个居民居住点之间可能有多条道路相连,也可能无路可通。有道路相连的居民居住点可以认为是一个灾民聚集区域,因为在这个区域内部还可以使用陆地交通工具进行物资的交换。由于洪灾发生的太突然,所有的人员都没有来得及转移,也就是说A地区所有居民居住点都有居民被困。为了尽快完成任务,政府需要知道至少需要多少船只,才能保证每个灾民聚集区域都有船只去解救。
输入
第一行是一个整数T,表示有T组测试样例(0 < T <= 50)。每个测试样例开始一行包括两个整数N,M,(0 < N <= 20,0 <= M <= 200)分别代表A地区有N个居民居住点,和M条保留下来的道路。下面的M行,每行有两个整数u,v,表示居民点u,v仍然有道路相连。保证u,v都在1-N的范围内,并且u ≠ v。
输出
每个测试样例输出一行,包括一个整数,即至少需要多少船只,才能保证每个灾民聚集区域都有船只去解救。
示例输入
2
3 1
1 2
3 2
3 2
1 2
示例输出
2
1
提示
来源
山东理工大学第三届ACM程序设计竞赛
解题报告:这道题真正的意思是要统计集合的个数,利用并查集即可!去年的校赛题!
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; const int MAX = 205; int T, N , M, ans; int father[MAX], map[MAX][MAX]; void Makeset()//初始化 { int i; for (i = 0; i< MAX; ++i) { father[i] = i; } } int Find(int x)//路径压缩 { if (father[x] != x) { father[x] = Find(father[x]); } return father[x]; } void Merge(int x, int y)//合并 { int i, j; i = Find(x); j = Find(y); if (i != j) { ans --;//集合的个数减一 if (i > j) { father[i] = j; } else { father[j] = i; } } } int main() { int i, p, q; scanf("%d", &T); while (T --) { scanf("%d%d", &N, &M); Makeset(); ans = N;//假设都没有相连 memset(map, 0, sizeof(map)); for (i = 1; i <= M; ++i) { scanf("%d%d", &p, &q); Merge(p, q); } printf("%d\n", ans); } return 0; }