zoukankan      html  css  js  c++  java
  • ACM题目————次小生成树

    Description

    最小生成树大家都已经很了解,次小生成树就是图中构成的树的权值和第二小的树,此值也可能等于最小生成树的权值和,你的任务就是设计一个算法计算图的最小生成树。

    Input

    存在多组数据,第一行一个正整数t,表示有t组数据。
    每组数据第一行有两个整数n和m(2<=n<=100),之后m行,每行三个正整数s,e,w,表示s到e的双向路的权值为w。

    Output

    输出次小生成树的值,如果不存在输出-1。

    Sample Input

    2
    3 3
    1 2 1
    2 3 2
    3 1 3
    4 4
    1 2 2
    2 3 2
    3 4 2
    4 1 2

    Sample Output

    4
    6

    克鲁斯卡尔算法。

    求一次是最小生成树,两次就是次小生成数了。

    //Asimple
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cctype>
    #include <cstdlib>
    #include <stack>
    #include <cmath>
    #include <string>
    #include <queue>
    #define INF 100000
    using namespace std;
    const int maxn = 210;
    typedef long long ll ;
    int fa[maxn];//并查集 
    int vis[maxn];//记录下标 
    int path;//记录最小生成树用到边的数量 
    int T, n, m;
    typedef struct node{
        int st;
        int ed;
        int w;
        bool operator < (const node& A) const {
            return w<A.w ;
        }
    }node;
    //初始化 
    void init(){
        //获取并查集的大小 
        int len = sizeof(fa)/sizeof(fa[0]);
        for(int i=0; i<len; i++){
            fa[i] = i;
        }
    }
    //并查集的查找——查找父节点
    int findfa(int x){
        int pa;
        if( x == fa[x] ) return x;
        pa = findfa(fa[x]);
        fa[x] = pa;
        return pa;
    }
    //求最小生成树 
    int minTree(node *points, int m, int n)  
    {  
        init();  
      
        int i, count, flag, pa, pb;  
      
        for (i = count = flag = path = 0; i < m; i ++) {  
            pa = findfa(points[i].st);  
            pb = findfa(points[i].ed);  
              
            if (pa != pb) {  
                vis[path ++] = i;  
                fa[pa] = pb;  
                count ++;  
            }  
      
            if (count == n - 1) {  
                flag = 1;  
                break;  
            }  
        }  
      
        return flag;  
    }  
      
    // 求次小生成树 
    int secMinTree(node *points, int m, int n)  
    {  
        int i, j, min, tmp, pa, pb, count, flag;  
      
        for (i = 0, min = INF; i < path; i ++) {  
            init();  
      
            // 求次小生成树  
            for (j = count = tmp = flag = 0; j < m; j ++) {  
                if (j != vis[i]) {  
                    pa = findfa(points[j].st);  
                    pb = findfa(points[j].ed);  
      
                    if (pa != pb) {  
                        count ++;  
                        tmp += points[j].w;  
                        fa[pa] = pb;  
                    }  
      
                    if (count == n - 1) {  
                        flag = 1;  
                        break;  
                    }  
                }  
            }  
      
            if (flag && tmp < min)   min = tmp;  
        }  
      
        min = (min == INF) ? -1 : min;  
      
        return min;   
    }
    int main(){
        node *p;
        scanf("%d",&T);
        while( T -- ){
            scanf("%d %d",&n, &m);
            p = (node *)malloc(sizeof(node) * m);
            for(int i=0; i<m; i++){
                scanf("%d %d %d",&p[i].st,&p[i].ed,&p[i].w);
            }
            sort(p,p+m);
            
            int f = minTree(p,m,n);
            
            if( f == 0 ){//无法生成最小生成树
                printf("-1
    ");
                continue; 
            } else {
                int Min = secMinTree(p,m,n);
                printf("%d
    ",Min);
            }
            //释放p 
            free(p);
        }
        return 0;
    }       
    低调做人,高调做事。
  • 相关阅读:
    python | if else || where true 流程控制
    python |生成器
    python| 什么是迭代器?
    Python -WordCloud安装、词云制作
    技巧 |Python 使用dict.fromkeys()快速生成一个字典
    python 列表(list)去重方法总结
    区别 |python 的read、readline、readlines和write、writelines
    区别 |Python的 open() 和with open() as
    散点图和气泡图的几种制作方法
    宽表和窄表的建设该如何选择?
  • 原文地址:https://www.cnblogs.com/Asimple/p/5715563.html
Copyright © 2011-2022 走看看