zoukankan      html  css  js  c++  java
  • 最小生成树 tree(陈立杰)

    问题 D: tree
    时间限制: 3 Sec 内存限制: 512 MB
    提交: 24 解决: 7
    [提交][状态][讨论版]
    题目描述
    给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
    题目保证有解。
    输入
    第一行V,E,need分别表示点数,边数和需要的白色边数。
    接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。
    输出
    一行表示所求生成树的边权和。
    V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。
    样例输入
    2 2 1
    0 1 1 1
    0 1 2 0
    样例输出
    2
    因为当前最小生成树上的白边是不确定的,所以通过修改白边的优先级来改变生成树上白边的数量。那么怎么修改呢?改边权。当然就想到二分答案了,给白边加上当前二分的值(-100,100)如果白边过多,加大值,过少反之。
    注意,会有很多边边权一样,这时,白边数量q>k也可以是成立的(只要把一些等权的白边改成黑边就行了)注意最后答案要减去need*mid(二分的值)

         #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,k,mid,e,ans,q,adj[50005],f[50005];
    struct road
    {
        int u,v,next,l,h;
        bool friend operator <(road a,road b)
        {
            return a.l!=b.l ? a.l<b.l : a.h<b.h;
        }
    }lu[100005];
    void add(int u,int v,int l,int h)
    {lu[++e].u=u;lu[e].h=h;lu[e].v=v;lu[e].l=l;lu[e].next=adj[u];adj[u]=e;}
    inline int find(int x){return f[x]==x ? x:f[x]=find(f[x]);}
    inline void hb(int x,int y){int fx=find(x),fy=find(y);if(fx!=fy)f[fx]=fy;}
    inline int read()
    {
        int sum=0,f=1;char x=getchar();
        while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
        while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
        return sum*f;
    }
    int check()
    {
        ans=0;q=0;int w=0;
        for(int i=1;i<=m;i++)if(!lu[i].h)lu[i].l+=mid;
        sort(lu+1,lu+m+1);
        for(int i=0;i<n;i++)f[i]=i;
        for(int i=1;i<=m;i++)
        {
            if(find(lu[i].u)!=find(lu[i].v))
            {
                w++;
                hb(lu[i].u,lu[i].v);
                ans+=lu[i].l;
                if(!lu[i].h)q+=1;
            }
            if(w==n-1)break;
        }
        for(int i=1;i<=m;i++)if(!lu[i].h)lu[i].l-=mid;
        //cout<<q<<" "<<ans<<endl;
        if(q>=k)return 1;
        return 0;
    }
    int yjn()
    {
    //  freopen("nt2012_tree.in","r",stdin);
    //  freopen("nt2012_tree.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        int x,y,z,h;
        for(int i=1;i<=m;i++)
        {
            x=read();y=read();z=read();h=read();
            add(x,y,z,h);
        }
        int l=-100,r=100,w=0;
        while(l<=r)
        {
            mid=(l+r)/2;
            if(check())
          {
               l=mid+1,w=ans-k*mid;
           }
           else r=mid-1;
       }
        cout<<w;
    }
    int qty=yjn();
    int main(){;}
  • 相关阅读:
    vue中使用better-scroll实现滑动效果
    better-scroll一个好用的页面滑动工具
    display:table和display:table-cell结合使用
    大小图片
    axios的使用
    vue中两种路由跳转拼接参数
    Android 核心分析 之七Service深入分析
    Android 核心分析 之六 IPC框架分析 Binder,Service,Service manager
    Android 核心分析 之五基本空间划分
    Android核心分析之四手机的软件形态
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632703.html
Copyright © 2011-2022 走看看