zoukankan      html  css  js  c++  java
  • 最小生成树

    1. Problem Description

    如题,给出一个无向图,求出最小生成树

    2. Input

    第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

    接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

    3. Output

    输出包含一个数,即最小生成树的各边的长度之和;

    输入样例#1:

    4 5 1 2 2 1 3 2 1 4 3 2 3 4 3 4 3 输出样例#1:

    7

      

      Kruskal算法证明:如果某个连通图属于最小生成树,那么所有从外部连接到该连通图的边中的一条最短的边必然属于最小生成树。所以不难发现,当最小生成树被拆分成彼此独立的若干个连通分量的时候,所有能够连接任意两个连通分量的边中的一条最短边必然属于最小生成树

      尤其注意变量total。

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int par[51000],rnk[5100];
     5 const int inf=1<<30;
     6 int n,m;
     7 struct edge{
     8     int u,v,cost;
     9 }a[201000]; 
    10 bool cmp(const edge&a,const edge &b){
    11     return a.cost<b.cost;
    12 }
    13 int find(int x){
    14     if(par[x]==x)    return x;
    15     else {
    16         return par[x]=find(par[x]);
    17     }
    18 }
    19 void unite(int x,int y){
    20     x=find(x),y=find(y);
    21     if(x==y) return ;
    22     if(rnk[x]<rnk[y])    par[x]=y;
    23     else {
    24         par[y]=x;
    25         if(rnk[x]==rnk[y])    rnk[x]++;
    26     }
    27 }
    28 bool same(int x,int y) {
    29     return find(x)==find(y);
    30 }
    31 int main(){
    32     cin>>n>>m;
    33     for(int i=0;i<n;i++){
    34         par[i]=i;
    35     } 
    36     for(int i=0;i<m;i++){
    37     scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].cost);
    38     }
    39     sort(a,a+m,cmp);
    40     ll ans=0;edge e;    int total=0; 
    41     for(int i=0;i<m;i++){
    42         e=a[i];
    43         if(!same(e.u,e.v)){
    44             unite(e.u,e.v);
    45             ans+=e.cost;
    46             total++;
    47             if(total==n-1)break;
    48         }
    49         
    50     }
    51     bool flag=1;
    52     for(int i=1;i<n;i++){
    53         if(find(i)!=find(0)){
    54             flag=0;
    55             break;
    56         }
    57     }
    58     if(flag)    cout<<ans<<endl;
    59     else cout<<"orz
    ";
    60     return 0;
    61 }
  • 相关阅读:
    转载 Android Permission中英对照
    常用vi命令——鸟哥的私房菜
    转载 Android拍照、录像、录音代码范例
    转载 Android ListView滚动提示等待框
    Android ViewFlipper装载baseAdapter
    转载 Android解决java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    转载 Android解决通过Intent调用系统拍照程序,返回图片太小的问题
    垂直输出字符串数组
    Yahoo!网站性能最佳体验的34条黄金守则__JavaScript和CSS
    将16进制转换成10进制
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/9797585.html
Copyright © 2011-2022 走看看