zoukankan      html  css  js  c++  java
  • [vijos1234]口袋的天空<最小生成树>

    题目链接:https://vijos.org/p/1234

    白天刚刚写完prim的算法,晚上就心血来潮的打了一道最小生成树的题

    虽然有题解说可以用prim做,但是这道题明显是加最小的边,感觉kruskal方便多了

    但是愉快的是我竟然不是一次过,最后发现是题意理解问题,我之前读了很多遍题,还是以为n朵云不用用完,但其实是n朵云要用完并成为k个棉花糖

    首先可以知道的是,k个棉花糖中有k-1个是单个的云,因为单个的云就是不要花费的,所以生成树就是在剩下的n-k+1朵云中产生,然后这n-k+1朵云最多用n-k+1-1条边连接是最优的,所以其实就是kruskal选出n-k+1-1条边的最小价值

    然后就是一个裸的kruskal了,然后由于很久没打kruskal了,我竟然自作聪明的加了vis数组,然后光荣爆零,最后删去vis,只用并查集判断就瞬间a了

    果然是我太弱了吗

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #define maxn 10005
     8 using namespace std;
     9 
    10 struct edge{
    11     int  u,v,w;
    12 }e[2*maxn];
    13 
    14 int n,m,k,pos,tot,ans;
    15 int head[maxn],fa[maxn];
    16 
    17 int read(){
    18     int xx=0,ff=1;char ch=getchar();
    19     while(ch<'0'||ch>'9'){if(ch=='-')ff=-1;ch=getchar();}
    20     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
    21     return xx*ff;
    22 }
    23 
    24 void adde(int u,int v,int w){
    25     e[++pos].u=u;
    26     e[pos].v=v;e[pos].w=w;
    27 }
    28 
    29 int comp(const void*a,const void*b){
    30     return (*(struct edge*)a).w>(*(struct edge*)b).w?1:-1;
    31 }
    32  
    33 int find_(int x){
    34     if(fa[x]==x)return fa[x];
    35     return fa[x]=find_(fa[x]);
    36 } 
    37  
    38 int main(){
    39     scanf("%d",&n);m=read();k=read();
    40     for(int i=1;i<=m;i++){
    41         int u,v,w;
    42         u=read();v=read();w=read();
    43         adde(u,v,w);
    44     }    
    45     if(k>n){
    46         printf("No Answer");return 0;
    47     }
    48     for(int o=1;o<=n;o++)
    49         fa[o]=o;
    50     qsort(e,m+1,sizeof(e[0]),comp);
    51     for(int i=1;i<=m;i++){
    52         int u=e[i].u,v=e[i].v;
    53         int fu=find_(u);int fv=find_(v);
    54         if(fu!=fv){
    55             fa[fu]=fv;
    56             tot++;vis[fv]=1;ans+=e[i].w;
    57         }
    58         if(tot>=n-k+1-1){
    59             printf("%d",ans);return 0;
    60         }
    61     }
    62     printf("No Answer");
    63 }
    kruskal

    【总结】

    头可断,血可流,代码错不得

    注意判断选入边的条件,理解并查集的运用,不能死记硬背

  • 相关阅读:
    BUG漏测的原因总结,以及如何处理
    费用流
    拉格朗日插值
    数论问题整理
    计数问题
    POJ 1741 Tree
    bzoj 2820: YY的GCD
    luogu P3690 【模板】Link Cut Tree (动态树)
    bzoj 1036: [ZJOI2008]树的统计Count
    bzoj 3282: Tree
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7749238.html
Copyright © 2011-2022 走看看