• poj2421 Constructing Roads


    题目地址:http://poj.org/problem?id=2421

    题意:给你n个点,然后求最小生成树。特殊之处在于有一些点之间已经连上了边。

    思路:使用kruscal算法,对于已经有边的点,特殊标记一下,加边的时候把这些边的权值赋值为0即可。这样就可以既保证这些边一定存在,又保证了所求的结果正确。

    #include <iostream>  
    #include <stdio.h>  
    #include <algorithm>  
    #include <string.h>  
    #define N 100
    using namespace std;  
      
    
     
    int father[N];  
    struct edge{  
        int lp,rp,value;  
    }ee[N*N];//结构体数组来存储边的顶点和权值
    
    
      
    int map[N][N],flag[N][N],numedge,n;
    int i,j;  
    bool cmp(edge a,edge b){  
        return a.value < b.value;  
    }  //按权值来排序
    int find(int x){  
        if(x == father[x])  
            return father[x];  
        return find(father[x]);  
    }  
    bool merge(int x,int y){  
        int fx = find(x);  
        int fy = find(y);  
        if(fx == fy){  
          return false;  
        }  
        else{  
          father[fx] = fy;  //加入同一集合
          return true;  
        }  
    }  //并查集的查找
    int kruskal(){  
        sort(ee,ee+numedge,cmp);  //排序
        for(i = 1; i <= n; ++i)  
            father[i] = i;        //初始化并查集
        int sum = 0;  
        for(j = 0; j < numedge; ++j){  
            int lx = ee[j].lp;  
            int rx = ee[j].rp;  
            if(merge(lx,rx)){ //判断是否在同一集合中,若不是则加入同一集合并且将权值相加 
                sum += ee[j].value;  
            }  
        }  
        return sum;  
    }  
    int main(){  
         
        while(scanf("%d",&n) != EOF){  
            
            for(i = 1; i <= n; ++i){  
              for(j = 1; j <= n; ++j)  
                  scanf("%d",&map[i][j]);  
            }  
            int m,x,y;  
            scanf("%d",&m);  
            while(m--){  
              scanf("%d%d",&x,&y);  
              flag[x][y] = 1;  
            } //对于已有边相连的节点将其标志数组设为1 
            numedge = 0;  
            for(i = 1; i < n; ++i){  
                for(j = i + 1; j <= n; ++j){  
                    if(flag[i][j]){  
                        ee[numedge].lp = i;  
                        ee[numedge].rp = j;  
                        ee[numedge].value = 0;  
                        numedge++;  //对于已访问过的节点来说,将其边的权值置0,但是边的数量+1
                    }  
                    else{  
                        ee[numedge].lp = i;  
                        ee[numedge].rp = j;  
                        ee[numedge].value = map[i][j];  
                        numedge++;  //对于未访问的节点,将其存储在map数组中的边的权值赋给结构体中的权值,边的数量++
                    }  
                }  
            }  
            int ans = kruskal();  //通过编写的函数将所有结构体数组中的元素按权值排序,在判断不为同一集合后依次从小到大将权值相加,并将相加过的边的顶点归为同一集合
            printf("%d
    ",ans);   //将统计后的最小权值之和输出
        }  
        return 0;  
    }
  • 相关阅读:
    Servlet基本用法(一)基本配置
    python 起航第一步吧
    shell脚本的执行方式
    linux 计划任务执行命令 crontab -e
    一个完整的 curl post登录带验证码的代码
    php curl post登录与带cookie模拟登录随笔
    liunx 配置 php curl 拓展库的方法
    php 魔术方法学习笔记
    php curl选项列表(超详细)
    正则表达式后面接的/isU, /is, /s含义
  • 原文地址:https://www.cnblogs.com/jokerspace/p/6753188.html
Copyright © 2020-2023  润新知