zoukankan      html  css  js  c++  java
  • 找朋友

    找朋友

    【试题描述】

    老师要去统计班里的人际情况。

    班里共有n名同学,编号从1到n。班上共有m对朋友。

    现在,老师希望快速地知道,每名同学都有哪些朋友。

    【输入要求】

    输入的第一行包含两个整数n, m。
    接下来m行,每行2个正整数编号,表示这两名同学是朋友。

    【输出要求】

    输出共n行,第i行的格式为:Friends of i : i所有朋友的编号。注意后输入的朋友先输出,详见样例。

    【输入实例】

    6 5
    1 2
    1 6
    4 5
    1 4
    5 6
    

      

    【输出实例】

    Friends of 1 : 4 6 2
    Friends of 2 : 1
    Friends of 3 :
    Friends of 4 : 1 5
    Friends of 5 : 6 4
    Friends of 6 : 5 1
    

      

    【其他说明】

    对于40%的数据,n<=1000;
    对于100%的数据,n<=100000,m<=200000。

    【试题分析】

    想想要用什么做?果断!第一反应:邻接矩阵and并查集

    #include<iostream>
    using namespace std;
    int f[301000],a[301000][301000],k[301000],maxn;
    void cy(int f[],int x,int y)
    {
        int t=f[x],t1=f[y];
        for(int i=0;i<1010;i++)
            if(f[i]==t) f[i]=t1;
    }
    int main()
    {
        int num=0,n,i,m,x,y;
        scanf("%d%d",&m,&n);
        for(i=0;i<1010;i++) f[i]=i;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            maxn=max(maxn,max(x,y));
            if(f[x]==f[y]);
            else cy(f,x,y);
            a[x][k[x]++]=y,a[y][k[y]++]=x;
        }
        for(int i=1;i<=maxn;i++)
        {
            cout<<"Friends of "<<i<<" :";
            for(int j=k[i]-1;j>=0;j--)
                cout<<" "<<a[i][j];
            cout<<endl;
        }
    }
    

        如果你是这样按邻接矩阵开一个可怕的二维数组的话,恭喜你,内存爆了,电脑炸了。要是这样你还不如干脆开小一点空间,这样不至于一上来直接就炸内存,我们还可以骗一点分。

        很显然,正解是不会让你有机会开二维数组的,3十万乘3十万。

    而还有一种神奇的方法:邻接表。

        我们可以试一试这个程序:

        

    int n,m,i;
    int u[1006],v[1006];
    int first[1005],next[1005];
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) first[i]=-1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&u[i],&v[i]);
        next[i]=first[u[i]];
        first[u[i]]=i;
    }
    for(i=1;i<=n;i++)
    {
        int k=first[i];
        while(k!=-1)
        {
             printf("%d %d",u[k],v[k]);
             k=next[k];
        }
    cout<<endl; }

    加上正规语法后,运行一下,看看有没有什么发现?

    很明显输出的是:

    1 41 61 2
    
    
    4 5
    5 6
    

    啊!!第一行表示第一个人与四六二是朋友,与输出样例一样!

    但是2的时候怎么没有输出1??

    很明显,上面只输出了前面没有输出过的。

    那么,怎么输出后面的呢?

    我们要解决两个难题:

    1.输出后面的。

    2.后输入的先输出。

    其实只要解决第一个,第二个就自然而然解决了。

    我们只需双向储存一下就可以了。

    既然要双向储存,我们就必须数组开两倍大。注意!少开的代价是很惨的!少乘一个二可能会在全国联赛中直接丢掉30+分!!而这三十分可能让你从银牌获得金牌或进入国家队!!

    【代码】

    #include<iostream>
    #include<cstring>
    using namespace std;
    inline int read()
    {
        int x,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
        return x*f;
    }
    int u[200100],v[200100];
    int first[400200],next[400200];
    int main()
    {
        int n=read(),m=read(),k;
        memset(first,-1,sizeof(first));
        for(int i=1;i<=m*2;i+=2)
        {
            u[i]=read(),v[i]=read();
            u[i+1]=v[i],v[i+1]=u[i];//双向储存
            next[i]=first[u[i]];
            first[u[i]]=i;
            next[i+1]=first[u[i+1]];
            first[u[i+1]]=i+1;                                                             
        }
        for(int i=1;i<=n;i++)
        {
            k=first[i];
            printf("Friends of %d :",i);
            if(first[i]==-1) {printf("
    ");continue;}
            while(k!=-1)
            {
                printf(" %d",v[k]);
                k=next[k];
            }
            printf("
    ");
        }
    }
    
  • 相关阅读:
    搜狗输入法赏析
    第二次冲刺个人总结05
    程序员的自我修养阅读笔记01
    第十五周学习总结
    mysql 查询优化
    mysql explain 详解
    nginx基本配置与参数说明
    input输入框实现联想关键词功能
    JS图片懒加载
    mysql中timestamp,datetime,int类型的区别与优劣
  • 原文地址:https://www.cnblogs.com/wxjor/p/5708481.html
Copyright © 2011-2022 走看看