zoukankan      html  css  js  c++  java
  • hdu 4253(二分+最小生成树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4253

    思路:求最小生成树是显然的,题目还多了一个限制条件,就是属于A公司的边必须有K条,于是我们可以二分来实现这个目的,找一个尽量大的mid,用A公司的每条边都加上这个mid,使得求出的最小生成树中包含A公司的边至少K条,于是花费ans=sum-K*mid。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 #define MAXN 50000+50
     7 #define MAXM 100000+100
     8 #define inf 1<<30
     9 int parent[MAXN];
    10 struct Edge{
    11    int u,v,w;
    12 }W[MAXM],B[MAXM];
    13 int n,m,k,sum,cnt,cntw,cntb;
    14 
    15 int Find(int x)
    16 {
    17    if(x==parent[x])
    18       return x;
    19    parent[x]=Find(parent[x]);
    20    return parent[x];
    21 }
    22 
    23 int cmp(const Edge &p,const Edge &q)
    24 {
    25    return p.w<q.w;
    26 }
    27 
    28 bool Union(int u,int v)
    29 {
    30    int r1=Find(u),r2=Find(v);
    31    if(r1==r2)return false;
    32    parent[r1]=r2;
    33    return true;
    34 }
    35 
    36 bool Judge(int w)
    37 {
    38    for(int i=0;i<=n;i++)
    39       parent[i]=i;
    40    cnt=sum=0;
    41    int la=0,lb=0;
    42    while(la<cntw||lb<cntb){
    43       if(W[la].w+w<=B[lb].w){
    44          if(Union(W[la].u,W[la].v)){ sum+=W[la].w+w;cnt++; }
    45          la++;
    46       }else{
    47          if(Union(B[lb].u,B[lb].v))sum+=B[lb].w;
    48          lb++;
    49       }
    50    }
    51    if(cnt>=k)return true;
    52    return false;
    53 }
    54 
    55 
    56 int main()
    57 {
    58   // freopen("1.txt","r",stdin);
    59    int u,v,w,tag,ans,t=1;
    60    while(~scanf("%d%d%d",&n,&m,&k)){
    61       cntw=cntb=0;
    62       while(m--){
    63          scanf("%d%d%d%d",&u,&v,&w,&tag);
    64          if(tag){ B[cntb].u=u,B[cntb].v=v,B[cntb++].w=w; }
    65          else { W[cntw].u=u,W[cntw].v=v,W[cntw++].w=w; }
    66       }
    67       sort(B,B+cntb,cmp);
    68       sort(W,W+cntw,cmp);
    69       B[cntb].w=W[cntw].w=inf;
    70       int l=-100,r=100,mid;
    71       while(l<=r){
    72          mid=(l+r)>>1;
    73          if(Judge(mid)){
    74             ans=sum-mid*k;
    75             l=mid+1;
    76          }else
    77             r=mid-1;
    78       }
    79       printf("Case %d: %d\n",t++,ans);
    80    }
    81    return 0;
    82 }
    View Code
  • 相关阅读:
    java回顾之多线程
    java回顾之异常
    模拟斗地主和冒泡排序
    java回顾之Map
    java回顾之集合List
    java回顾之树
    java回顾之单列集合、泛型、数据结构
    java回顾之类API再体验之引用类型小结
    java回顾之API初体验
    函数之 闭包函数 和 装饰器
  • 原文地址:https://www.cnblogs.com/wally/p/3131104.html
Copyright © 2011-2022 走看看