zoukankan      html  css  js  c++  java
  • 典型问题--连通性

    1.问题示例

    201206181513342042 (1)

    如果新输入的对,可以由以前的输入对连通,就不会输出;如果不能由以前的对连通,就输出这个对。例如2-9不在输出之列,因为前面的对存在2-3-4-9的连通。

    2.算法实现

    抽象操作:

    ·查找已有的数据项集合

    ·将结果合并到数据项集合中

    2.1 快速查找算法

    #include <stdio.h>
    #define N 10000
    void main()
    {
        int i, p, q, t, id[N];
        for(i = 0; i < N; i++)
            id[i] = i;
        while (scanf("%d-%d\n", &p, &q) == 2)
        {
            if(id[p] == id[q])
                continue;
            //遍历数组,把所有值等于id[q]的元素的值改为id[p]。
            for(t = id[p], i = 0; i < N; i++)
                if(id[i] == t)
                    id[i] = id[q];
            printf(" %d-%d\n", p, q);
        }
    }

    未命名

              图2-1 快速查找示例(慢速合并)

    当id[p] = id[q]时,表示p和q连通。

    2.2  快速合并算法

    #include <stdio.h>
    #define N 10000
    main()
    {
        int i, j, p, q, id[N];
        for(i = 0; i < N; i++)
            id[i] = i;
        while (scanf("%d-%d\n", &p, &q) == 2)
        {
            for(i = p; i != id[i]; i = id[i]) ;   //查找p所在树1的根节点
            for(j = q; j != id[j]; j = id[j]) ;   //查找q所在树2的根节点 
            if(i == j)
                continue;
            id[i] = j;   //树2连入树1
            printf(" %d-%d\n", p, q);
        }
    }

    201206181514002274201206181514106429

          图2-2 快速合并算法示例(不是太快的查找)

    2.3 加权快速合并算法

    利用数组sz[N]记录了树的节点数,保证每次合并时将较小的树根连到较大的树根上面,避免产生太深的树,减少查找遍历次数。

    #include <stdio.h>
    #define N 10000
    void main()
    {
        int i, j, p, q, id[N], sz[N];
        for(i = 0; i < N; i++)
        {
            id[i] = i;
            sz[i] = 1;
        }
        while (scanf("%d-%d\n", &p, &q) == 2)
        {
            for(i = p; i != id[i]; i = id[i]) ;
            for(j = q; j != id[j]; j = id[j]) ;
            if(i == j)
                continue;
            if(sz[i] < sz[j])
            {
                id[i] = j;
                sz[j] += sz[i];
            }
            else
            {
                id[j] = i;
                sz[i] += sz[j];
            }
            printf(" %d %d\n", p, q);
        }
    }

    201206181514153892

     图2-3 加权快速合并算法的树型表示

    这颗树中每个节点到根节点的距离变小,因而查找更高效。

    2.3 等分路径压缩

    代替2.2中的for循环,通过使每条链接跳跃到树中向上的路径的下一个节点实现压缩。

    for(i = p; i != id[i]; i = id[i]) 
        id[i] = id[id[i]];
    for(j = q; j != id[j]; j = id[j]) 
        id[j] = id[id[j]];

    201206181514256410

      图2-3  等分路径压缩

    当处理1和6的时候,让1、5、6都指向3,得到的树比上面的算法更扁平。

    2.4 完全路径压缩

    在合并操作的过程中,添加经过每条路径的另一个指针,使沿路遇见的每个顶点对应的id元素指向树的根节点。

    #include <stdio.h>
    #include <stdlib.h>
    #define BUFFER_MAX_SIZE 16
    int main(int argc, char *argv[]) 
    {
        int con[BUFFER_MAX_SIZE];
        int con_cnt[BUFFER_MAX_SIZE];
        int elem[BUFFER_MAX_SIZE][BUFFER_MAX_SIZE];
        int elem_cnt[BUFFER_MAX_SIZE];
        int p, q, r, i, j, k;
        for(r=0; r<BUFFER_MAX_SIZE; r++) 
        {
            con[r]=r;
            con_cnt[r]=1;
            elem[r][0]=r;
            elem_cnt[r]=1;
        }
        
        while(scanf("%d-%d", &p, &q)==2) 
        {
            if(p>=BUFFER_MAX_SIZE||q>=BUFFER_MAX_SIZE)
                exit(EXIT_FAILURE);
            for(i=p; i!=con[i]; i=con[i]);
            for(j=q; j!=con[j]; j=con[j]);
            if(i==j)
                continue;
            if(con_cnt[i]<con_cnt[j]) 
            {
                k=elem_cnt[j];
                for(r=0; r<elem_cnt[i]; r++)
                    elem[j][elem_cnt[j]++]=elem[i][r];
                for(r=k; r<elem_cnt[j]; r++)
                    con[elem[j][r]]=j;
                con_cnt[j]+=con_cnt[i];
            }
            else 
            {
                k=elem_cnt[i];
                for(r=0; r<elem_cnt[j]; r++)
                    elem[i][elem_cnt[i]++]=elem[j][r];
                for(r=k; r<elem_cnt[i]; r++)
                    con[elem[i][r]]=i;
                con_cnt[i]+=con_cnt[j];
            }
            printf("%d-%d\n", p, q);
            for(r=0; r<BUFFER_MAX_SIZE; r++)
                printf("%d\t", con[r]);
            printf("\n");
        }
        exit(EXIT_SUCCESS);
    }
  • 相关阅读:
    企业级应用TOMCAT
    HTTP服务及状态码
    Zabbix服务网页报错汇总
    spring aop 嵌套方法注解不生效
    oracle数据库密码修改和解锁
    redis安装
    docker简介
    ffmpeg简介
    JAVA学习笔记之变量
    JAVA学习笔记之类和对象
  • 原文地址:https://www.cnblogs.com/onetaste/p/2667036.html
Copyright © 2011-2022 走看看