码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2654 tree

时间:2015-01-28 00:58:11      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:

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

 

数据规模和约定

  0:V<=10

  1,2,3:V<=15

  0,..,19:V<=50000,E<=100000

  所有数据边权为[1,100]中的正整数。

 
这题还是蛮好玩的
首先,直接做MST的话白色边的数量是无法估计的。可能比要求的多,也可能更少
所以考虑怎样调整白色边的数量
通过这个思路,可以想到如果把所有白色边的权值加上/减去一个Δ,那么不考虑答案正确性,可以保证这时候MST跑出来之后白色边的数量一定会增加/减少
那么我们就可以直接二分一个值,使得白边的数量符合要求。
事实上可以证明当我们限定白边的数量一定的时候,MST的答案也是唯一的
那么我们在白边上加上Δ之后算出来MST的答案会多出need*Δ,直接减掉就好了
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct ed{int x,y,z,color;}e[100010];
struct bian{int x,y,z,mrk;}a[100010];
inline bool operator<(const bian &a,const bian &b){return a.z<b.z||a.z==b.z&&a.mrk>b.mrk;}
int n,m,k,ans,tot,sum,tt;
int fa[100010];
inline int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
inline void jud(int mid)
{
    tot=sum=0;
    for (int i=1;i<=n;i++)fa[i]=i;
    for (int i=1;i<=m;i++)
    {
        a[i].x=e[i].x;
        a[i].y=e[i].y;
        a[i].z=e[i].z+(e[i].color*mid);
        a[i].mrk=e[i].color;
    }
    sort(a+1,a+m+1);
    for (int i=1;i<=m;i++)
    {
        int fx=getfa(a[i].x),fy=getfa(a[i].y);
        if (fx==fy)continue;
        if (a[i].mrk)tot++;
        fa[fx]=fy;
        sum+=a[i].z;
    }
}
int main()
{
    n=read();m=read();k=read();
    for (int i=1;i<=m;i++)
    {
        e[i].x=read()+1;
        e[i].y=read()+1;
        e[i].z=read();
        e[i].color=read()^1;
        if (e[i].color)tt++;
    }
    int l=-105,r=105;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        jud(mid);
        if (tot>=k){ans=sum-k*mid;l=mid+1;}
        else r=mid-1;
    }
    printf("%d\n",ans);
    return 0;
}

 

bzoj2654 tree

标签:

原文地址:http://www.cnblogs.com/zhber/p/4254745.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!