zoukankan      html  css  js  c++  java
  • hdu 4253 Two Famous Companies BZOJ 2654 tree

    【题意】:给出n个点,m条边,边分为两种,一种是A公司的,一种是B公司的。边上有权值,问用n-1条边把n个点连起来的最小费用是多少,其中A公司的边刚好有k条。题目保证有解。

    思路:我们发现,如果我们给白边增加权值,做最小生成树,由于白边权值增大,导致不容易选白边。记f(x)为给白边增加x权值,做最小生成树后,选白边的数量,可以发现,f(x)随x增大而减小。所以可以二分x

    首先,直接做MST的话白色边的数量是无法估计的。可能比要求的多,也可能更少

    所以考虑怎样调整白色边的数量
    通过这个思路,可以想到如果把所有白色边的权值加上/减去一个Δ,那么不考虑答案正确性,可以保证这时候MST跑出来之后白色边的数量一定会增加/减少
    那么我们就可以直接二分一个值,使得白边的数量符合要求。
    事实上可以证明当我们限定白边的数量一定的时候,MST的答案也是唯一的
    那么我们在白边上加上Δ之后算出来MST的答案会多出need*Δ,直接减掉就好了
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 struct node
      7 {
      8     int v1,v2;
      9     int w;
     10 } s[100005],t[100005];
     11 int n,m,k,cnts,cntt;
     12 int father[100005],sum;
     13 int cmp(const node a,const node b)
     14 {
     15    return a.w<b.w;
     16 }
     17 int find(int x)
     18 {
     19     int i=x,root;
     20     while(x!=father[x])
     21         x=father[x];
     22     root=x;
     23     x=i;
     24     while(x!=father[x])
     25     {
     26         i=father[x];
     27         father[x]=root;
     28         x=i;
     29     }
     30     return root;
     31 }
     32 int deal(int x)
     33 {
     34     for(int i=0; i<=n; i++)
     35         father[i]=i;
     36     int lens=0,lent=0,pp=0;
     37     sum=0;
     38     while(lens<cnts||lent<cntt)
     39     {
     40 
     41         if(s[lens].w+x<=t[lent].w)
     42         {
     43             int s1=find(s[lens].v1);
     44             int s2=find(s[lens].v2);
     45             if(s1!=s2)
     46             {
     47                 father[s1]=s2;
     48                 sum+=s[lens].w+x;
     49                 pp++;
     50             }
     51             lens++;
     52         }
     53         else
     54         {
     55             int s1=find(t[lent].v1);
     56             int s2=find(t[lent].v2);
     57             if(s1!=s2)
     58             {
     59                 father[s1]=s2;
     60                 sum+=t[lent].w;
     61             }
     62             lent++;
     63         }
     64 
     65     }
     66     if(pp>=k)   return 1;
     67     else    return 0;
     68 }
     69 int main()
     70 {
     71     int text=0;
     72     while(scanf("%d%d%d",&n,&m,&k)>0)
     73     {
     74         cnts=0,cntt=0;
     75         for(int i=0; i<m; i++)
     76         {
     77             int v1,v2,w,tmp;
     78             scanf("%d%d%d%d",&v1,&v2,&w,&tmp);
     79             if(tmp==0)
     80             {
     81                 s[cnts].v1=v1;
     82                 s[cnts].v2=v2;
     83                 s[cnts].w=w;
     84                 cnts++;
     85             }
     86             if(tmp==1)
     87             {
     88                 t[cntt].v1=v1;
     89                 t[cntt].v2=v2;
     90                 t[cntt].w=w;
     91                 cntt++;
     92             }
     93         }
     94         sort(s,s+cnts,cmp);
     95         sort(t,t+cntt,cmp);
     96         t[cntt].w=s[cnts].w=(1<<29);
     97         printf("Case %d: ",++text);
     98         int l=-1000,r=1000;
     99         int ans=0;
    100         while(l<=r)
    101         {
    102             //sum=0;
    103             int mid=(l+r)/2;
    104             if(deal(mid))
    105             {
    106                 l=mid+1;
    107                 ans=sum-mid*k;
    108             }
    109             else r=mid-1;
    110         }
    111         printf("%d
    ",ans);
    112     }
    113     return 0;
    114 }
  • 相关阅读:
    Understanding Paths in ASP.NET
    C#通过shell32来控制本地连接
    利用outlook发邮件
    角色扮演游戏引擎的设计原理[转载]
    Lvalues and Rvalues
    链接字符串里面不要加上connection timeout =0
    Winform获取当前拥有焦点的控件
    Spring 3.x jar 包详解 与 依赖关系
    Liferay环境搭建、简单说明与相关资料
    爆音(杂音)问题的推论与解决
  • 原文地址:https://www.cnblogs.com/tsw123/p/4440002.html
Copyright © 2011-2022 走看看