SDUT 1918 运送物资(并查集的应用)

运送物资

Time Limit: 1000MS Memory limit: 65536K

题目描述

A地区发生了洪灾,造成部分道路被毁,通信中断。为了先安顿受灾群众,政府决定利用船只向各个灾民聚集区域运送救灾物资。已知A地区共有居民居住点N个,编号为1-N,受灾后经过卫星拍摄的图片发现还有M条道路可用,并且两个居民居住点之间可能有多条道路相连,也可能无路可通。有道路相连的居民居住点可以认为是一个灾民聚集区域,因为在这个区域内部还可以使用陆地交通工具进行物资的交换。由于洪灾发生的太突然,所有的人员都没有来得及转移,也就是说A地区所有居民居住点都有居民被困。为了尽快完成任务,政府需要知道至少需要多少船只,才能保证每个灾民聚集区域都有船只去解救。

输入

第一行是一个整数T,表示有T组测试样例(0 < T <= 50)。每个测试样例开始一行包括两个整数NM(0 < N <= 20,0 <= M <= 200)分别代表A地区有N个居民居住点,和M条保留下来的道路。下面的M行,每行有两个整数uv,表示居民点uv仍然有道路相连。保证uv都在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;
}

 

 

 

原文地址:https://www.cnblogs.com/lidaojian/p/2459000.html