关闭

【九度】题目1526:朋友圈

789人阅读 评论(0) 收藏 举报
分类:

题目1526:朋友圈

题目描述:
      假如已知有n个人和m对好友关系(存于数字r)。如果两个人是直接或间接的好友(好友的好友的好友...),则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈。
      假如:n = 5 , m = 3 , r = {{1 , 2} , {2 , 3} , {4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,则1、2、3属于一个朋友圈,4、5属于另一个朋友圈,结果为2个朋友圈。
输入:
      输入包含多个测试用例,每个测试用例的第一行包含两个正整数 n、m,1=<n,m<=100000。接下来有m行,每行分别输入两个人的编号f,t(1=<f,t<=n),表示f和t是好友。 当n为0时,输入结束,该用例不被处理。
输出:
      对应每个测试用例,输出在这n个人里一共有多少个朋友圈。
样例输入:
5 3
1 2
2 3
4 5
3 3
1 2
1 3
2 3
0
样例输出:
2
1
【解题思路】
这应该是并查集最简单的应用了,求集合个数。
基本思路:
1、每次输入节点的时候,就合并。
2、依次查找每个节点的父节点。
3、放在set中,set.size()即为朋友圈的个数。
并查集的应用很多,在很多时候效率比prim以及Dijkstra算法效率要高。
后面会有一些题两者都可以做出。我会给出比较。
C++ AC

#include <stdio.h>
const int maxn = 100002;
int parent[maxn];
int n;
int m;
int i;
 
int findParent(int f) {  
    while(parent[f] != f){
        f = parent[f];
    }
    return f;
}  
 
void unionTwo(int f, int t) {  
             
    int a = findParent(f);  
    int b = findParent(t);  
    if (a == b) return;   
    if (a > b) {     
        parent[a] = b;     
    } else {  
        parent[b] = a;   
    }  
}  
 
 
int main(){
    while(scanf("%d",&n) != EOF){
        if(n == 0){
          break;
        }
        scanf("%d",&m);
        if(n == 1){
            printf("1\n");
        }else{
            for(i = 1; i < n+1; i++){
                parent[i] = i;
            }
            for(i = 0 ; i < m ; i++){
                int a, b;
                scanf("%d%d",&a,&b);
                unionTwo(a,b);
            }
            for (i = 1; i < n+1; i++) {  
                parent[i] = findParent(i);  
            }
            int num = 0;
            for(i = 1; i < n+1; i++){
                if(parent[i] == i){
                    num ++;
                }
            }
            printf("%d\n",num);
        }
    }
    return 0;
}
/**************************************************************
    Problem: 1526
    User: wangzhenqing
    Language: C++
    Result: Accepted
    Time:210 ms
    Memory:1412 kb
****************************************************************/

Java AC

import java.io.StreamTokenizer;
import java.util.HashSet;
import java.util.Set;
 
public class Main {
     /*
     * 1526
     */
    public static void main(String[] args) throws Exception{
        StreamTokenizer st = new StreamTokenizer(System.in);
        while (st.nextToken() != StreamTokenizer.TT_EOF) {
            int n = (int) st.nval;
            if (n == 0) {
                break;
            }
            if (n == 1) {
                System.out.println(1);
            }else {
                int []parent = new int[n+1];
                for (int i = 1; i <= n; i++) {
                    parent[i] = i;
                }
                st.nextToken() ;
                int m = (int) st.nval;
                for (int i = 0; i < m; i++) {
                    st.nextToken() ;
                    int f = (int) st.nval;
                    st.nextToken() ;
                    int t = (int) st.nval;
                    union(f ,t , parent );
                }
                 
                for (int i = 1; i < n+1; i++) {
                    parent[i] = findParent(i, parent);
                }
                Set<Integer> numSet = new HashSet<Integer>();
                for (int i = 1; i < n+1; i++) {
                    numSet.add(parent[i]);
                }
                System.out.println( numSet.size());
            }
        }
    }
  
    private static void union(int f, int t, int[] parent ) {
          
        int a = findParent(f , parent);
        int b = findParent(t , parent);
        if (a == b) return; 
        if (a > b) {   
            parent[a] = b;   
         } else {
            parent[b] = a; 
         }
    }
  
    private static int findParent(int f, int[] parent) {
        if (parent[f] == f) {
            return f;
        }
        return findParent(parent[f],parent );
    }
}   
/**************************************************************
    Problem: 1526
    User: wzqwsrf
    Language: Java
    Result: Accepted
    Time:970 ms
    Memory:42400 kb
****************************************************************/

其实在查找父节点的时候,不应该用递归,
直接用while效率比较高。
这在一些代码中有体现。
将parent[]声明为公共属性。
将以下这个方法修改为:
修改前:

private static int findParent(int f, int[] parent) {
    if (parent[f] == f) {
        return f;
    }
    return findParent(parent[f],parent );
}
修改后:

private static int findParent(int f) {
    while (parent[f] != f) {
        f = parent[f];
    }
    return f;
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:255156次
    • 积分:5149
    • 等级:
    • 排名:第5348名
    • 原创:263篇
    • 转载:16篇
    • 译文:0篇
    • 评论:47条
    博客专栏
    最新评论