zoukankan      html  css  js  c++  java
  • [20200717NOIP提高组模拟T3]水管

    题目大意:

      给你$n$个点和$m$条边,要求你输出最小生成树的边权之和并判断最小生成树是否唯一.

    solution:

      最小生成树板子,Kruskal即可.至于判断唯一性,这里有一种耐人寻味的解法.对于每一个边权值$z$,我们可以寻找所有边权与其相等的边并统计其中合法边数sum,然后再扫描一次选其中足够的合法边并加入最小生成树,如果有剩余的合法边,则说明可以替换,即最小生成树不唯一.

    code:

      

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define R register
    #define next exnt
    #define debug puts("mlg")
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void writesp(ll x);
    inline void writeln(ll x);
    inline void write(ll x);
    ll T;
    ll n,m;
    struct node{
        ll X,Y,Z;
    }t[220000];
    inline bool cmp(node x,node y){
        return x.Z<y.Z;
    }
    ll f[220000];
    inline void init(){
        for(R ll i=1;i<=n;i++) f[i]=i;
    }
    inline ll getf(ll x){
        return f[x]==x?x:f[x]=getf(f[x]);
    }
    inline bool check(ll x,ll y){
        return getf(x)==getf(y);
    }
    inline void merge(ll x,ll y){
        f[getf(y)]=getf(x);
    }
    ll sum,total,ans;
    int main(){
        T=read();
        while(T--){
            n=read(),m=read();
            init();
            for(R ll i=1;i<=m;i++) t[i].X=read(),t[i].Y=read(),t[i].Z=read();
            sort(t+1,t+m+1,cmp);
            total=ans=sum=0;
            for(R ll i=1;i<=m;i++){
                for(R ll j=i;j<=m&&t[j].Z==t[i].Z;j++){
                    if(!check(t[j].X,t[j].Y)){
                        ++sum;
                    }
                }
                do{
                    if(!check(t[i].X,t[i].Y)){
                        merge(t[i].X,t[i].Y);
                        ans+=t[i].Z;
                        ++total;
                    }
                    if(total==n-1) break;
                    ++i;
                }while(t[i].Z==t[i-1].Z&&i<=m);
                if(total==n-1) break;
                --i;
                
            }
            writeln(ans);
            if(sum>n-1) puts("No");
            else puts("Yes");
        }
    }
    inline ll read(){
        ll x=0,t=1;char ch=getchar();
        while(ch<'0'||ch>'9'){
            if(ch=='-') t=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*t;
    }
    inline void write(ll x){
        if(x<0){putchar('-');x=-x;}
        if(x<=9){putchar(x+'0');return;}
        write(x/10);putchar(x%10+'0');
    }
    inline void writesp(ll x){
        write(x);putchar(' ');
    }
    inline void writeln(ll x){
        write(x);putchar('
    ');
    }

    感谢机房神犇zxt提供思路

  • 相关阅读:
    VUE调用函数,以及event的讲解
    VUE双向绑定,以及表达式自增
    使用VUE的准备工作,以及显示文本
    MVC中VUE的学习
    Redis
    C# form表单提交enctype="multipart/form-data" 与 enctype="application/x-www-form-urlencoded" 两者之间的区别
    C# 导入导出
    文件压缩,解压缩
    [vue-router] Duplicate named routes definition: { name: "Front", path: "/home/front" }
    * @/components/widget/AddBands in ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/pages/Brands.vue
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13331397.html
Copyright © 2011-2022 走看看