宗教信仰,并查集

问题描述

世界上有许多宗教,你感兴趣的是你学校里的同学信仰多少种宗教。
你的学校有n名学生(0 < n <= 50000),你不太可能询问每个人的宗教信仰
因为他们不太愿意透露。但是当你同时找到2名学生,他们却愿意告诉你他们是否信仰同一宗教
你可以通过很多这样的询问估算学校里的宗教数目的上限。你可以认为每名学生只会信仰最多一种宗教。

Input

输入包括多组数据。
每组数据的第一行包括n和m,0 <= m <= n(n-1)/2,其后m行每行包括两个数字i和j,表示学生i和学生j信仰同一宗教,学生被标号为1至n。输入以一行 n = m = 0 作为结束。

Output

对于每组数据,先输出它的编号(从1开始),接着输出学生信仰的不同宗教的数目上限。

Sample Input

10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
10 4
2 3
4 5
4 8
5 8
0 0

Sample Output

Case 1: 1
Case 2: 7

 

归类算法,并查集

简单来说就是同样的人放入同样的集合,最后判断集合的个数

这里吐槽一下某些oj,格式错误也提示的是wrong answer

最后的Case写成case导致几个小时的欢乐时光就“pia”的没了

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<cstdio>
#include<queue>
#include<stack>

#define Watch_RunTime 1
#if Watch_RunTime
#include <ctime>
int start_time;
#endif


#define debug 1
#define Max 3000
using namespace std;

int findRoot(int s[], int x)
{
    while (s[x] >= 0)
        x = s[x];
    return x;
}

int main() {

    {
    #if debug
        freopen("in.txt", "r", stdin);
    #endif
    #if Watch_RunTime
        start_time = clock();
    #endif
    }

 


    int *a;
    int n, m,casee=0;
    while (1)
    {
        cin >> n >> m;
        if (m == 0 && n == 0)
            break;
        a = new int[n+1];
        memset(a, -1, sizeof(int)*(n+1));
        for (int k = 0; k < m; k++)
        {
            int i, j;
            cin >> i >> j;
            if(findRoot(a, j) != findRoot(a, i))
            a[findRoot(a, j)] = findRoot(a, i);
        }
        int count = 0;
        for (int k = 1; k <= n; k++)
        {
            if(a[k]==-1)
            count++;
        }
        cout <<"Case "<<++casee<<": "<< count<<endl;
        delete a;
    }


    {
    #if debug
        freopen("CON", "r", stdin);
    #endif
    #if Watch_RunTime
        cout << "\n\n\n\n-------\n";
        cout << clock() - start_time << "ms";
    #endif
    }


    system("pause>nul");
    return 0;
}

posted @ 2019-03-18 19:45  ecnu_lxz  阅读(239)  评论(0编辑  收藏  举报