找朋友

找朋友

【试题描述】

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

班里共有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("\n");continue;}
        while(k!=-1)
        {
            printf(" %d",v[k]);
            k=next[k];
        }
        printf("\n");
    }
}

 

posted @ 2016-07-26 18:12  wxjor  阅读(365)  评论(1编辑  收藏  举报