scau_大牛之路2(并查集)

原创 2015年11月20日 20:10:38

8618 大牛之路II

该题有题解

时间限制:500MS  内存限制:1000K
提交次数:138 通过次数:31

题型: 编程题   语言: G++;GCC

Description

要成为ACM大牛,要掌握很多必需的知识点。某些知识点可以推导出别的知识点,所以在比赛中遇到的新问题,
很多时候可以由你学过的知识中推导得到。现在给出要掌握的所有知识点数及知识点之间的推导关系。
注意,若A知识可以直接(间接)推导出B知识,B知识也是有可能直接(间接)推导出A知识的。
一个新手想尽快具有解决所有知识点的能力,他至少需要掌握多少知识呢?



输入格式

多组数据,每组数据格式为:
第一行1<=n<=18,0<=m<=n*n.。n表示必需掌握的知识点数目,编号0~n-1。m为知识点间推导关系总数。接下来m
行,每行A B两个数,表示从A知识可以推导出B知识。
当n==0 && m==0时,结束程序。两个Case间有一空行。


输出格式

一个数x,表示最少要掌握的知识数。


输入样例

8 4
0 1
0 2
1 3
1 4

2 2
0 1
1 0

0 0


输出样例

4
1

这道题用并查集思想能很高效解决,引用一下大神的代码
int pre[1000 ];
int find(int x)                                                                                        //查找根节点
{ 
    int r=x;
    while ( pre[r ] != r )                                                                  //返回根节点 r
          r=pre[r ];
 
    int i=x , j ;
    while( i != r )                                                                              //路径压缩
    {
         j = pre[ i ]; // 在改变上级之前用临时变量  j 记录下他的值 
         pre[ i ]= r ; //把上级改为根节点
         i=j;
    }
    return r ;
}
 
 
void join(int x,int y)                                                                      //判断x y是否连通,
                                              //如果已经连通,就不用管了 //如果不连通,就把它们所在的连通分支合并起,
{
    int fx=find(x),fy=find(y);
    if(fx!=fy)
        pre[fx ]=fy;
}


不过这道题得具体分析,比如路径压缩就不行了,这样会让知识的推导关系乱掉。同时推导方向是固定的,不是双向的,所以需要加上flag数组储存。
给出代码纪念
<pre name="code" class="cpp">#include <stdio.h>
#include <string.h>
int pre[20];
int flag[20];

int find(int x)
{
    int r=x;
    while(pre[r]!=r)
    {
        r=pre[r];
    }
   /* int i=x,j;
    while(i!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }*/
    return r;
}
int main()
{
    int n,m,i;
    while((scanf("%d %d",&n,&m)==2)&&(n||m))
    {
        memset(flag,0,sizeof(flag));
        int a,b,a1,b1,count=0;
        for(i=0;i<n;i++)
        {
            pre[i]=i;
        }
        while(m--)
        {
            scanf("%d %d",&a,&b);
            if(flag[b])
            continue;
            flag[b]=1;
            a1=find(a);
            b1=find(b);
            if(a1!=b1)
            {
                pre[b1]=a1;
            }
        }
        for(i=0;i<n;i++)
        {
            if(pre[i]==i)
            count++;
        }
        printf("%d\n",count);
    }
    return 0;
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

[ASP.NET MVC 大牛之路]03 - C#高级知识点概要(2) - 线程和并发

我也想过跳过C#高级知识点概要直接讲MVC,但经过前思后想,还是觉得有必要讲的。我希望通过自己的经验给大家一些指引,带着大家一起走上ASP.NET MVC大牛之路,少走弯路。同时也希望能和大家一起交流...

[ASP.NET MVC 大牛之路]02 - C#高级知识点概要(1) - 委托和事件

在ASP.NET MVC 小牛之路系列中,前面用了一篇文章提了一下C#的一些知识点。照此,ASP.NET MVC 大牛之路系列也先给大家普及一下C#.NET中的高级知识点。每个知识点不太会过于详细,但...

[ASP.NET MVC 大牛之路]01 - C#高级知识点概要(1) - 委托和事件

要成为大牛,必然要有扎实的基本功,不然时间再长项目再多也很难有大的提升。本系列讲的C# 高级知识点,是非常值得去撑握的,不仅可以让你写代码时游刃有余,而且去研究和学习一些开源项目时,也不会显得那么吃力...

linux多线程编程书籍推荐:linux大牛之路从这几本书开始总结

linux多线程编程是指基于Linux操作系统下的多线程编程,包括多任务程序的设计,并发程序设计,网络程序设计,数据共享等。Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Li...

并查集代码

  • 2015年12月12日 20:18
  • 1KB
  • 下载

HDU 4619 Warm up 2(贪心、并查集 | 二分图最大独立集)

题意: 1∗2的多米诺骨牌,n≤1000个横向的,m≤1000个纵向的1*2的多米诺骨牌, n\le 1000个横向的, m\le 1000个纵向的 横向的之间互相没有交点,纵向也是横向的之...
  • lwt36
  • lwt36
  • 2016年03月01日 02:44
  • 299

ACM并查集讲解的深化和扩展

  • 2016年07月01日 17:27
  • 1.58MB
  • 下载

并查集初步(黄劲松).ppt

  • 2015年04月01日 15:45
  • 424KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:scau_大牛之路2(并查集)
举报原因:
原因补充:

(最多只允许输入30个字)