• Evanyou Blog 彩带


      BZOJ传送门COGS传送门

    tree

    Description

    给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
    题目保证有解。

    Input

    第一行V,E,need分别表示点数,边数和需要的白色边数。
    接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。

    Output

    一行表示所求生成树的边权和。

    Sample Input

    2 2 1
    0 1 1 1
    0 1 2 0

    Sample Output

    2

    Hint

    V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。


      分析:

      在大鸡哥的博客里看到的,一开始的分析就是直接一波玄学排序然后暴力Kruskal+一堆判断,然后自己把自己推翻了。。。

      还是看了大鸡哥的博客才懂得。大鸡哥的博客里讲的很清晰了,而且还讲到了COGS上和BZOJ上数据不同的问题。就推荐一下大鸡哥的博客吧。

      Code:

    //It is made by HolseLee on 1st June 2018
    //BZOJ 2654/COGS 1764
    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e4+7;
    const int M=1e5+7;
    int n,m,k,fa[N],num,ans;
    struct Node{
    int from,to,val,c,id;
    }edge[M];
    inline int read()
    {
        char ch=getchar();int num=0;bool flag=false;
        while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
        while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
        return flag?-num:num;
    }
    inline bool cmp(Node a,Node b)
    {return a.c==b.c?a.id<b.id:a.c<b.c;}
    inline int find(int x)
    {return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline int check(int ka)
    {
        for(int i=1;i<=m;i++)
        edge[i].c=edge[i].val+(edge[i].id^1)*ka;
        sort(edge+1,edge+m+1,cmp);
        for(int i=0;i<n;i++)fa[i]=i;
        int cnt=0,tot=0;num=0;
        for(int i=1;i<=m;i++){
            int x=find(edge[i].from);
            int y=find(edge[i].to);
            if(x!=y){fa[y]=x;tot++;
            cnt+=(edge[i].id==0?1:0);
            num+=edge[i].c;}
            if(tot==n-1)break;}
        return cnt;
    }
    int main()
    {
        freopen("nt2012_tree.in","r",stdin);
        freopen("nt2012_tree.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&edge[i].from,&edge[i].to);
            scanf("%d%d",&edge[i].val,&edge[i].id);}
        int L=-100,R=100,mid;
        while(L<=R){
            mid=(L+R)/2;
            if(check(mid)>=k)ans=num-k*mid,L=mid+1;
            else R=mid-1;}
        printf("%d",ans);return 0;
    }
  • 相关阅读:
    mysql 快速生成百万条测试数据
    解决mysql插入数据l出现"the table is full"的问题
    php 判断设备是手机还是平板还是pc
    golang格式化输出-fmt包用法详解
    阿里云用smtp无法发送邮件
    百度文本编辑器的toolbars属性值描述
    beego register db `default`, sql: unknown driver "mysql" (forgotten import?)
    MQ知识点汇总
    redis知识点汇总
    知识体系
  • 原文地址:https://www.cnblogs.com/cytus/p/9123721.html
Copyright © 2020-2023  润新知