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

最小生成树:Tree

时间:2018-08-25 18:42:12      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:span   its   二分   最小生成树   name   tps   col   lse   scan   

参考资料:https://blog.csdn.net/sunshinezff/article/details/48749453

题解摘抄:

显然可以发现随着白边权值的增大。最小生成树中白边的个数不增。

然后根据这个性质我们就可以二分一个值,然后每次给白边加上这个值。看一下最小生成树中白边的个数。

最后答案再把它减去。

看起来思路非常简单,但是有一个很重要的细节。

如果在你的二分过程中如果给白边加上mid,你得到的白边数比need大。

给白边加上mid+1,你得到的白边比need小。

这种情况看似没法处理。

但是考虑一下克鲁斯卡尔的加边顺序。

可以发现如果出现这种情况,一定是有很多相等的白边和黑边。因为数据保证合法。

所以我们可以把一些白边替换成黑边。

所以我们要在白边数>=need的时候跟新答案。

具体用ans=ans-mid*need;即可。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int x,y,w,c;
}a[1100000];
int pre[6000000];
int v,e,need,s[6000000],t[6000000],c[6000000],col[6000000],m=0;
int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);
}
bool cmp(node a,node b){
    if(a.w==b.w) return a.c<b.c;//关键点 
    else
     return a.w<b.w;
}
int ans,tot;
int kruskal(int mid)
{
    int num=0;
    memset(a,0,sizeof a);
    for(int i=1;i<=e;i++)
    {
        a[i].x=s[i];
        a[i].y=t[i];
        a[i].c=col[i];
        a[i].w=c[i];
        if(a[i].c==0)
        {
            a[i].w+=mid;
        }
    }
    stable_sort(a+1,a+e+1,cmp);
    for(int i=0;i<=v+1;i++) pre[i]=i;//注意点
    int cnt=0;
    tot=0;
    for(int i=1;i<=e;i++)
    {
        int fx=find(a[i].x);
        int fy=find(a[i].y);
        if(fx!=fy){
            cnt++;
            tot+=a[i].w;
            pre[fx]=fy;
            if(a[i].c==0)
            {
                num++;
            }
            if(cnt==v-1) break;
        }
    }
    return num;
}
int main()
{
    scanf("%d%d%d",&v,&e,&need);
    for(int i=1;i<=e;i++)
    {
        scanf("%d%d%d%d",&s[i],&t[i],&c[i],&col[i]);
        s[i]++;t[i]++;
    }
    int l=-155555,r=155555;//注意点三 
    while(l<=r)
    {
        int mid=(l+r)/2;
        int a1=kruskal(mid);
        if(a1>=need)
        {
            l=mid+1;
            ans=tot-mid*need;//关键点 
        }
        else r=mid-1;
    }
    cout<<ans;
    return 0;
}

 

最小生成树:Tree

标签:span   its   二分   最小生成树   name   tps   col   lse   scan   

原文地址:https://www.cnblogs.com/719666a/p/9534804.html

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