• 洛谷P2840 [USACO20DEC]Moocast(gold)奶牛广播-金


    洛谷P2840 [USACO20DEC]Moocast(gold)奶牛广播-金
    就是最小生成树的模板题

    蒟蒻我在这这里使用的就是最好写的Kruskal算法

    (做这道题之前,最好先去把‘最小生成树模板’这道题先过了)

    但是,从哪里看出这是最小生成树是一个值得一提的问题(或者说如何构图)

    我的方法:以A~B为例子,AB这条边的边权就等于A点的值+B点的值+2*AB(因为这条路要来回走,共两遍)

    然后再找点的值最小的一个点,作为出发点,就可以愉快地跑Kruskal了

    下面是拙劣的代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=10005,M=100005;
     6 int p[N],f[N];
     7 struct Node{
     8     int u,v,w;//u->v的边,权值为w
     9 }a[M]; 
    10 int find(int x){//并查集找祖宗(划掉)祖先
    11     return f[x]==x?x:f[x]=find(f[x]);
    12 }
    13 bool cmp(Node a,Node b){
    14     return a.w<b.w;
    15 }
    16 inline int mn(int a,int b){
    17     return a<b?a:b;
    18 }
    19 int main (){
    20     int n,m,ans=1<<30;
    21     scanf ("%d%d",&n,&m);
    22     for (int i=1;i<=n;i++) scanf ("%d",&p[i]),ans=mn(ans,p[i]),f[i]=i;//注意,并查集中每个元素初始时自己都是自己的祖宗,所以f[i]=i
    23     for (int i=1;i<=m;i++){
    24         scanf ("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
    25         a[i].w*=2;
    26         a[i].w+=p[a[i].u]+p[a[i].v];//上面说的构图方法
    27     }
    28     sort(a+1,a+m+1,cmp);
    29     for (int i=1;i<=m;i++){//跑最小生成树
    30         int x=find(a[i].u),y=find(a[i].v);
    31         if (x!=y){//如果两个的祖宗不同(就是不在一个集合内)
    32             ans+=a[i].w;//这条边必须选
    33             f[x]=y;//合并两个集合
    34         }
    35     }
    36     printf ("%d",ans);
    37     return 0;
    38 }
  • 相关阅读:
    数据库是什么以及用来干嘛
    10.3
    10.2
    12.7
    12.5
    12.4
    12.3
    12.2
    12.1JOptionPane
    11.30eclipse常用快捷键
  • 原文地址:https://www.cnblogs.com/third2333/p/7655173.html
Copyright © 2020-2023  润新知