• HDU 1863 畅通工程 最小生成树


    思路:

      比较典型的最小生成树的题目了、、在这里用求最小生成树的经典算法K(Kruskal)算法和P(Prim)算法。我的 K 算法用的是结构体来存图,P 算法用的是邻接矩阵来存图,K算法的复杂度是O(ElogE),比较适用于稀疏图,P算法的复杂的是O(V ^ 2),适合用稠密图。

    以下是C++的K算法代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <cctype>
     7 #include <algorithm>
     8 using namespace std;
     9 
    10 const int MAXN = 2e3+ 3;
    11 int pre[MAXN];
    12 int m,n;
    13 
    14 int Find(int x)  //并查集
    15 {
    16     return x == pre[x] ? x :(pre[x] = Find(pre[x]));
    17 }
    18 
    19 struct Node //存图
    20 {
    21     int u, v, w;
    22 }cy[103];
    23 
    24 int mycmp(Node a,Node b)
    25 {
    26     return a.w < b.w;
    27 }
    28 
    29 void mst()
    30 {
    31     for(int i = 0 ; i < 102; i++)
    32         pre[i] = i;
    33 }
    34 
    35 int kru()//算法的具体实现
    36 {
    37     int ans = 0;
    38     int cnt = 0;
    39     for(int i = 1; i <= n; i++)
    40     {
    41         int fv = Find(cy[i].v);
    42         int fu = Find(cy[i].u);
    43         if(fv != fu)
    44         {
    45             pre[fv] = fu;
    46             ans += cy[i].w;
    47             cnt ++;
    48         }
    49         if(cnt == m -1)
    50         {
    51             return ans;
    52             break;
    53         }
    54     }
    55     return -1;
    56 }
    57 
    58 int main()
    59 {
    60     //freopen("in.cpp","r",stdin);
    61     while(~scanf("%d%d",&n,&m) && n)
    62     {
    63         mst();
    64         for(int i = 1; i <= n; i++)
    65             scanf("%d%d%d",&cy[i].u, &cy[i].v, &cy[i].w);
    66         sort(cy + 1, cy + n + 1, mycmp);
    67         int ans = kru();
    68         if(ans != -1)
    69             printf("%d
    ",ans);
    70         else
    71             printf("?
    ");
    72     }
    73     return 0;
    74 }



    以下是C++的P算法代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <cctype>
     7 #include <algorithm>
     8 using namespace std;
     9 
    10 const int MAXN = 103;
    11 const int INF = 0x3f3f3f3f;
    12 int edge[MAXN][MAXN];   //用于存放图
    13 int used[MAXN];//用于标记点是否已加入到最小生成树那个的集合中
    14 int lowcost[MAXN];   //用于存放集合外的点到集合内的点的最短距离,每加入一个点需要更新一次
    15 int N,M;
    16 
    17 int prim(int start,int maxn)  //利用prim算法计算最小生成树
    18 {
    19    memset(used, 0, sizeof(used));
    20    for(int i = 1; i <= maxn; i++)
    21    {
    22        lowcost[i] = edge[start][i];
    23    }
    24    used[start] = 1;
    25    int sumweight = 0;
    26    int ok = 0;
    27    for(int i = 1; i <= maxn; i++)
    28    {
    29        int minn = INF ;
    30        int v = -1;
    31        for(int j = 1; j <= maxn; j++)
    32        {
    33            if(used[j] == 0 && lowcost[j] < minn)
    34            {
    35                minn = lowcost[j];
    36                v = j;
    37            }
    38        }
    39        //cout << v << " ";
    40        if(v != -1)
    41        {
    42            ok++;
    43            used[v] = 1;
    44            sumweight += lowcost[v];
    45            for(int j = 1; j <= maxn; j++)
    46            {
    47                if(used[j] == 0 && lowcost[j] > edge[v][j])
    48                {
    49                    lowcost[j] = edge[v][j];
    50                }
    51            }
    52        }
    53    }
    54    if(ok == maxn -1)
    55      return sumweight;
    56    return -1;
    57 }
    58 
    59 int main()
    60 {
    61     while(cin >> N >> M && N)
    62     {
    63         memset(edge, 0x3f, sizeof(edge));
    64         while(N--)
    65         {
    66             int u, v, w;
    67             cin >> u >> v >> w;
    68             edge[u][v] = edge[v][u] = w;
    69         }
    70         int ans = prim(1, M);
    71         if(ans < 0) cout << "?" <<endl;
    72         else cout << ans << endl;
    73     }
    74     return 0;
    75 }

    以下是JAVA的K算法

     1 import java.util.Scanner;
     2 import java.util.Comparator;
     3 import java.util.Arrays;
     4 import java.text.DecimalFormat;
     5 
     6 class Vge{
     7     int u;
     8     int v;
     9     int w;
    10 }
    11 
    12 class mycmp implements  Comparator<Vge>{
    13     public int compare( Vge A, Vge B ){  
    14             if( A.w - B.w != 0 )   
    15                 return A.w - B.w;  
    16             else 
    17                 return A.w - B.w;  
    18       }  
    19 }
    20 
    21 public class Main{
    22     final static int MAXN = 100 + 3;
    23     static int[] pre = new int[ MAXN ];
    24     static Vge[] clg = new Vge[ MAXN * MAXN ];
    25     public static void main( String[] args ){
    26         Scanner sc = new Scanner( System.in );
    27         int n, m;
    28         while( sc.hasNextInt() ){
    29             n = sc.nextInt();
    30             m = sc.nextInt();
    31             if( n == 0 ) break;
    32             for( int i = 0; i < n; i++ ){
    33                 clg[ i ] = new Vge();
    34                 clg[ i ].u = sc.nextInt();
    35                 clg[ i ].v = sc.nextInt();
    36                 clg[ i ].w = sc.nextInt();
    37             }
    38             mst( m );
    39             int ans = ksu( n, m );
    40             if( ans == -1 ) System.out.println( "?" );
    41             else System.out.println( ans );
    42         }
    43         sc.close();
    44     }
    45     public static void mst( int n ){
    46         for( int i = 0; i <= n; i++ ){
    47             pre[i] = i;
    48         }
    49     }
    50     public static int find( int x ){
    51         return x == pre[ x ] ?   x :  ( pre[ x ] = find( pre[ x ] ) );
    52     }
    53     public static int ksu( int n, int m ){
    54         Arrays.sort( clg, 0, n, new mycmp() );
    55         int cnt = 0;
    56         int ans = 0;
    57         for( int i = 0; i < n; i++ ){
    58             int fu = find( clg[ i ].u );
    59             int fv = find( clg[ i ].v );
    60             if( fu != fv ){
    61                 ans += clg[i].w;
    62                 cnt ++;
    63                 pre [ fv ] = fu;
    64             }
    65             if( cnt == m - 1 ) return ans;
    66         }
    67         return -1;
    68     }
    69 }
  • 相关阅读:
    最近的题越来越难了,卧槽,搞一上午一题不会,题解也看不懂
    hdu 4630 树状数组 ****
    hdu 3473 划分树 ***
    hdu 3360 最小点覆盖 **
    hdu 1507 记录路径的二分匹配 **
    poj 3177 边双联通 **
    hdu 4612 边双联通 ***
    Elasticsearch聚合后分页深入详解
    redis 五种数据类型及其使用场景
    再有人问你分布式锁,这篇文章扔给他
  • 原文地址:https://www.cnblogs.com/Ash-ly/p/5397646.html
Copyright © 2020-2023  润新知