朋友圈

来源:互联网 发布:无线点菜软件 编辑:程序博客网 时间:2024/04/28 17:02

参看 并查集的tutorial http://blog.csdn.net/jiyanfeng1/article/details/8083789

参考 基于并查集的算法 http://blog.csdn.net/jiyanfeng1/article/details/39257119


假如已知有n个人和m对好友关系,如果两个人是直接或者间接有好友关系,则认为他们属于同一个朋友圈。写程序判断里面有多少朋友圈。

例如:
n = 5, m = 3  r = {(1,2), (2, 3), (4, 5)}  1 2 3 是一个朋友圈, 4 5 是一个朋友圈。

所以输出是2.


下面的算法是基于图论中的深度优先的思想。

#include <STDIO.H>  #include <WINDOWS.H>      int Friends(int n, int m , int* r[]);    int main(int argc,char** argv)  {     int r[5][2] = {{1,2},{4,3},{6,5},{7,8},{7,9}};       printf("有%d个朋友圈。\n",Friends(0,5,(int**)r));    return 0;  }    int Friends(int n, int m, int* r[]) // 注意这里的参数很奇葩    {       int *p = (int*)malloc(sizeof(int)*m*3);      memset(p,0,sizeof(int)*m*3);    int i = 0;      int iCount = 0;      int j = 0;      int * q = (int*)r; // 这里很巧妙  将二维指针 强转为一维指针      for (i=0;i<m;++i)    {      for (j=0;j<2;++j)      {        p[i*3+j]=q[i*2+j];   // 注意这里二维数组向一维数组的转换      }        p[i*3+j] = 0;    }      bool bFlag = false;      for (i=0;i<m;++i)    {      bFlag = false;      if (p[i*3+2]==1)      {         bFlag = true;      }      p[i*3+2] = 1;      for (j=0;j<m;++j)      {        if (i==j)        {          continue;        }                  if (p[i*3]==p[j*3] ||          p[i*3] == p[j*3+1] ||          p[i*3+1] == p[j*3+0] ||          p[i*3+1] == p[j*3+1])        {          if (p[j*3+2]==1)          {            bFlag = true;          }          p[j*3+2] = 1;        }      }        if (!bFlag)      {        ++iCount;      }    }      free(p);         return iCount;  }  

另外一个更加简洁的算法是:基于图论的广度优先算法。

给定保存了朋友关系的数组 r ,然后依次扫描数组 r 中的朋友

如果数组中的一对朋友hash set里面找不到,那么朋友圈个数就加1,并且把这两个人加入到 hash set 里。

如果这一对朋友里的任何一个人,在hash set 里找的到,那么朋友圈个数不变,并把这两个人中另外一个不在hash set里的人加入到hash set 里 (如果两个人都已经在hashet 里,那么就什么都不做。)