zoukankan      html  css  js  c++  java
  • [bzoj1232][Usaco2008Nov]安慰奶牛cheer_Kruskal

    安慰奶牛 cheer bzoj-1232 Usaco-2008 Nov

    题目大意:给定一个n个点,m条边的无向图,点有点权,边有边权。FJ从一个点出发,每经过一个点就加上该点点权,每经历一条边就加上该边的边权。FJ必须经过所有点并回到出发点,求最小值。

    注释:$1le nle 10^4$,$1le mle 10^5$。


    想法

      显然最后的一条路径的并是整个图的一棵生成树。

      紧接着我们发现,这个图的值就是欧拉遍历序上,如果出现了这个点,就加上这个点的点权。边权乘2。

      所以我们将原图中的每条边变成自己的边权val_edge*2加上val[x]+val[y]。其中x和y是这条边连接的两个点。

      用kruskal求最小生成树即可。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 10010 
    #define M 100010 
    using namespace std; typedef long long ll; ll ans=0x7f7f7f7f; int tot=0; ll c[N]; int fa[N];
    struct Edge{int x,y; ll z;}a[M]; inline bool cmp(const Edge &l,const Edge &r) {return l.z<r.z;}
    inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
    int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
    int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline bool merge(int x,int y)
    {
        x=find(x); y=find(y);
        if(x==y) return false;
        fa[x]=y; return true;
    }
    int main()
    {
        int n=rd(),m=rd(); for(int i=1;i<=n;i++) c[i]=rd(),fa[i]=i,ans=min(ans,c[i]);
        for(int i=1;i<=m;i++) a[i].x=rd(),a[i].y=rd(),a[i].z=rd(),a[i].z=a[i].z*2+c[a[i].x]+c[a[i].y];
        sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++)
        {
            if(merge(a[i].x,a[i].y))
            {
                tot++; ans+=a[i].z;
            }
            if(tot==n-1) {printf("%lld
    ",ans); return 0;}
        }
    }
    

    小结:巧妙的题!

  • 相关阅读:
    记一次博客被日的分析过程
    省钱版----查找 IoT 设备TTL线序__未完待续
    于bugku中游荡意外得到关于CBC翻转攻击思路
    清除浮动技巧总结
    程序猿的幸福
    Memcachedclientutils类
    leetcode 2 Add Two Numbers
    arduino小车入门教学——第三天(arduino基础)
    SAP MM模块 经常使用函数
    Java代码格式
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9661719.html
Copyright © 2011-2022 走看看