zoukankan      html  css  js  c++  java
  • 【20180807模拟测试】tree

    题目描述

    或许会传送失败的传送门

    #分析

    考虑如何才能让白边显得更(不)重要,即在每条白边上(加上)减去一个值。
    我们可以二分这个值,然后用寻常方法做最小生成树。统计在此最小生成树里有多少白 边。
    然后我们就可以找到一个合适的值,带这个权做一次最小生成树。
    在计算答案的时候把这些值补偿回去就做完了。

    以上来自某标答

    关于各种调试时的槽点
    1.二分卡死的情况,什么l==r然后死循
    2.sum必须在外面减去增加的值(这可真是个未解之谜)(为什么不可以边做边补偿?边做边补偿只有40分。。。)
    3.你以为我写的是前向星吗。。。你可看到了head数组?对,就是没用了。kruskal表示我用不上那东西

    关于考试
    还有40分钟
    emm先20分钟来个Kruskal的小板,一看就和最小生成树有关(题干)
    然后?然后就瓜不瓜?瓜哉瓜哉,瓜了10分钟
    然后又开始了玄学贪心,先把最小的k条白边加进去骗分
    骗了10分

    以下正解

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,k,sum,cnt=0,x[1000010],y[1000001],z[1000001],c[1000001],fa[1000001];
    struct node{
        int u,v,w,c;
    }e[2000001];
    bool comp(node p,node q){
        if(p.w==q.w)return p.c<q.c;
          return p.w<q.w;
    }
    int getfa(int x){
        if(fa[x]!=x)
          fa[x]=getfa(fa[x]);
        return fa[x];
    }
    void add(int x,int y,int z,int c){
        e[++cnt].u=x;e[cnt].v=y;e[cnt].w=z;e[cnt].c=c;
    }
    bool Kruskal(int mid){
        int tot=0,ans=0;
        sum=0;
        for(int i=0;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            add(x[i],y[i],z[i],c[i]);
            if(c[i]==0)
              e[cnt].w+=mid;
        }
        sort(e+1,e+m+1,comp);
        for(int i=1;i<=m;++i){
            int p=getfa(e[i].u),q=getfa(e[i].v);
            if(p!=q){
                fa[p]=q;
                tot++;
                sum+=e[i].w;
                if(e[i].c==0)ans++;
            }
            if(tot>=n-1)
              break;
        }
        cnt=0;
        if(ans>=k)return true;
        else return false;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++)
          scanf("%d%d%d%d",&x[i],&y[i],&z[i],&c[i]);
        int l=-100,r=100;
        while(l<r){
            int mid=(l+r+1)/2;
            if(Kruskal(mid))l=mid;
            else r=mid-1;
        }
        Kruskal(l);
        printf("%d",sum-k*l);
        return 0;
    }
  • 相关阅读:
    PAT-乙级-1011. A+B和C (15)
    PAT-乙级-1010. 一元多项式求导 (25)
    PAT-乙级-1009. *说反话 (20)
    PAT-乙级-1008. 数组元素循环右移问题 (20)
    PAT-乙级-1007. 素数对猜想 (20)
    PAT-乙级-1006. 换个格式输出整数 (15)
    PAT-乙级-1005. 继续(3n+1)猜想 (25)
    PAT-乙级-1004. 成绩排名 (20)
    BZOJ 1030: [JSOI2007]文本生成器
    BZOJ 2938: [Poi2000]病毒
  • 原文地址:https://www.cnblogs.com/lisuier/p/9535098.html
Copyright © 2011-2022 走看看