zoukankan      html  css  js  c++  java
  • [题解]How Many Tables HDU

    题目描述

    Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with strangers.

    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.

    薇薇学姐今天请吃饭. 她邀请了很多朋友 (都是表面兄弟)。现在该吃饭了。薇薇学姐想知道她至少需要多少张桌子。但是不是所有的人都互相认识,所有的人都不想和陌生人坐在一起 (假装矜持)。

    但是如果A认识B, B认识C,那A, B, C就假装认识,所以他们就可以在一张桌子上吃饭。

    如果A知道B, B知道C, D知道E,那么A、B、C可以留在一起,而D、E必须在另一张桌子吃饭。至少需要两张桌子。

    输入

    The 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.

    输入以一个整数T(1<=T<=25)开始,它表示测试用例的数量。然后是测试用例。每个测试用例都以两个整数N和M开始(1<=N,M<=1000)。N表示朋友的数量,从1到N标记朋友,之后的M行,每一行由两个整数A和B(A!=B)组成,这意味着朋友A和朋友B相互认识。两种情况之间会有一条空行。

    输出

    For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks.

    对于每个测试用例,只需输出至少需要多少张桌子。不要打印任何空格。

    样例输入

    2
    5 3
    1 2
    2 3
    4 5

    5 1
    2 5

    样例输出

    2
    4

    题解

    本题算是很简单的并查集模板题,只需要计算有多少个集合就好了。

    对了记得要初始化,我的初始化改了一天才发现。
    WA代码,提供来让大家以此为戒:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    int t;
    int n, m;
    int pa[1010];
    int w[1010];
    int ans;
    int find(int k)
    {
    	while(pa[k] != k)
    	{
    		k = pa[k];
    	}
    	return k;
    }
    int main()
    {
    	scanf("%d", &t);
    	for(int i = 1; i <= t; i++)
    	{
    		ans = 0;
    		for(int j = 1; j <= n; j++)
    			w[j] = 0;
    		scanf("%d%d", &n, &m);
    		for(int j = 1; j <= n; j++)
    			pa[j] = j;
    		for(int j = 1; j <= m; j++)
    		{
    			int a, b;
    			scanf("%d%d", &a, &b);
    			if(a > b)
    			{
    				int l = a;
    				a = b;
    				b = l;
    			}
    			pa[b] = a;
    		}
    		for(int j = 1; j <= n; j++)
    			w[find(j)] = 1;
    		for(int j = 1; j <= n; j++)
    			if(w[j] == 1)
    				ans++;
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

    代码是存在问题的,我们首先要比较两个人是否本来就是朋友(或朋友的朋友),而不是直接连接起来,而且连接起来是用find(x)与find(y)连接,而不是他们俩直接合并。
    AC代码:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    int t;
    int n, m;
    int pa[1010];
    int w[1010];
    int ans;
    int find(int k)
    {
    	while(pa[k] != k)
    	{
    		k = pa[k];
    	}
    	return k;
    }
    int main()
    {
    	scanf("%d", &t);
    	for(int i = 1; i <= t; i++)
    	{
    		ans = 0;
    		for(int j = 1; j <= n; j++)
    			w[j] = 0;
    		scanf("%d%d", &n, &m);
    		for(int j = 1; j <= n; j++)
    			pa[j] = j;
    		for(int j = 1; j <= m; j++)
    		{
    			int a, b;
    			scanf("%d%d", &a, &b);
    			if(a > b)
    			{
    				int l = a;
    				a = b;
    				b = l;
    			}
    			/*改为以下代码就对了*/
    			a = find(a);
    			b = find(b);
    			if(a != b)
    				pa[b] = a;
    		}
    		for(int j = 1; j <= n; j++)
    			w[find(j)] = 1;
    		for(int j = 1; j <= n; j++)
    			if(w[j] == 1)
    				ans++;
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

    如果你觉得这篇题解对你有帮助,那就点个推荐吧,然后关注。
    也!

  • 相关阅读:
    FR #3题解
    L3-005. 垃圾箱分布
    L2-004. 这是二叉搜索树吗?
    L2-002. 链表去重
    L1-009. N个数求和
    L3-003. 社交集群
    L3-004. 肿瘤诊断
    L2-001. 紧急救援
    L3-002. 堆栈
    L2-007. 家庭房产
  • 原文地址:https://www.cnblogs.com/ahann/p/12667144.html
Copyright © 2011-2022 走看看