zoukankan      html  css  js  c++  java
  • 7-31 朋友圈 (25 分)(并查集)

    7-31 朋友圈 (25 分)

    某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。

    输入格式:

    输入的第一行包含两个正整数N(≤30000)和M(≤1000),分别代表学校的学生总数和俱乐部的个数。后面的M行每行按以下格式给出1个俱乐部的信息,其中学生从1~N编号:

    第i个俱乐部的人数Mi(空格)学生1(空格)学生2 … 学生Mi

    输出格式:

    输出给出一个整数,表示在最大朋友圈中有多少人。

    输入样例:

    7 4
    3 1 2 3
    2 1 4
    3 5 6 7
    1 6
    

    输出样例:

    4

    思路:类似与并查集的合并,对每个俱乐部看成一个集合,然后对这些集合进行合并

    第一种暴力:

    但是TLE:

    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    
    using  namespace std;
    int pre[30005];
    int find(int x)
    
    {
    	if(x==pre[x])
    	{
    		return x;
    	}
    	else
    	{
    		return pre[x]=find(pre[x]);
    	}
    }
    void merge(int x,int y)
    {
    	int xx=find(x);
    	int yy=find(y);
    	if(xx!=yy)
    	{
    		pre[xx]=yy;
    	 } 
    }
    
    int main()
    {
        int n,m;
        cin>>n>>m;
        for(int t=1;t<=n;t++)
        {
        	pre[t]=t;
    	}
    	int b[1005];
        for(int t=0;t<m;t++)
        {
        	int k;
        	scanf("%d",&k);
        	for(int j=0;j<k;j++)
        	{
        		scanf("%d",&b[j]);
    		}
    		for(int j=0;j<k-1;j++)
    		{
    			merge(b[j],b[j+1]);
    		}
    	}
    	long long int maxn=0;
    	for(int t=1;t<=n;t++)
    	{
    		long long int sum=0;
    		if(find(t)==t)
    		{
    			for(int j=1;j<=n;j++)
    			{
    				if(find(j)==t)
    				{
    					sum++;
    				}
    			}
    		}
    		if(maxn<sum)
    		{
    			maxn=sum;
    		}
    	}
    	cout<<maxn<<endl;
    	return 0;
    }

    第二种利用类似于前缀和的思想进行求最大值,即可少一个循环的量,从而提高效率;

    AC代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    
    using  namespace std;
    int pre[30005];
    long long int summ[30005];
    int find(int x)
    
    {
    	if(x==pre[x])
    	{
    		return x;
    	}
    	else
    	{
    		return pre[x]=find(pre[x]);
    	}
    }
    void merge(int x,int y)
    {
    	int xx=find(x);
    	int yy=find(y);
    	if(xx!=yy)
    	{
    		pre[xx]=yy;
    		summ[yy]+=summ[xx];
    	 } 
    }
    
    int main()
    {
        int n,m;
        cin>>n>>m;
        
        for(int t=1;t<=n;t++)
        {
        	pre[t]=t;
        	summ[t]=1;
    	}
    	int b[1005];
        for(int t=0;t<m;t++)
        {
        	int k;
        	scanf("%d",&k);
        	for(int j=0;j<k;j++)
        	{
        		scanf("%d",&b[j]);
    		}
    		for(int j=0;j<k-1;j++)
    		{
    			merge(b[j],b[j+1]);
    		}
    	}
    	long long int maxn=0;
    	for(int t=1;t<=n;t++)
    	{ 
    	  maxn=max(maxn,summ[t]);
    	}
    	cout<<maxn<<endl;
    	return 0;
    }
  • 相关阅读:
    linq to access 简单实现 实例demo
    FCKEDITOR中文使用说明 js调用
    asp.net mvc 随想
    fccms 小型简单个人blog源码
    PHP文件上传路径
    前端优化技巧(一)
    会话框拖拽效果实现
    phpmailer配置
    上传图片动态预览(兼容主流浏览器)
    Java将多个list对象根据属性分组后合并成一个新的集合
  • 原文地址:https://www.cnblogs.com/Staceyacm/p/10781950.html
Copyright © 2011-2022 走看看