关闭

scau_大牛之路2(并查集)

440人阅读 评论(0) 收藏 举报
分类:

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;
}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:30512次
    • 积分:2707
    • 等级:
    • 排名:第13851名
    • 原创:253篇
    • 转载:3篇
    • 译文:0篇
    • 评论:3条
    最新评论