[BZOJ1196][HNOI2006]公路修建问题(最小生成树)

=== ===

这里放传送门

=== ===

题解

一开始有一个比较明显的思路就是先把一级边单独排序然后往里加加到k条停下然后剩下的再用二级边补起来。但是这样做对不对呢?选择的一级边一定是最小的k条吗?有没有可能选一条稍微大一点的一级边,然后这样就能选进去一条稍微小一点的二级边然后达到降低最小边的目的呢?
然后ATP就开始画。。。画了一会儿以后感觉是不可能的。。
因为这种做法的本质是用某两条边替换掉了另外两条边,那么假如一开始选的两条边是A1和A2,后来替换掉的是B1和B2,那么肯定有B1>=A1并且B2 < <script type="math/tex" id="MathJax-Element-107"><</script>A2。又因为替换完了以后最大边变小了,所以原来的最大边是A2,那么就有A2>=B1。
因为要求的是一个最小生成树,所以当A1和A2没有加进去的时候图中有三个连通块。又因为这里涉及到了4条不同的边,那么肯定有至少一对边连接了两个相同的连通块,它们不能同时被选。
那么对这一对不能同时被选的边进行讨论。假如A1和B2可以同时被选,那么选A1和B2肯定更优,因为A1是两条一级边中的较小者,B2是两条二级边中的较小者;假如A1和B2不能同时被选,因为A2>B1,而B1>=B1对应的那条二级边,所以选择A1和B1对应的那条二级边肯定是最优的。不管怎样都不可能跳过A1选择B1。
也就是说选择的一级边一定是能选的最小k条,所以这种做法是正确的。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,k,father[10010],sum,cnt;
struct edge{
    int x,y,w;
    edge(int X=0,int Y=0,int W=0){x=X;y=Y;w=W;}
}e1[20010],e2[20010];
int comp(edge a,edge b){return a.w<b.w;}
int find(int x){
    if (x==father[x]) return x;
    father[x]=find(father[x]);
    return father[x];
}
int main()
{
    scanf("%d%d%d",&n,&k,&m);
    for (int i=1;i<=m;i++){
        int x,y,c1,c2;
        scanf("%d%d%d%d",&x,&y,&c1,&c2);
        e1[i]=edge(x,y,c1);
        e2[i]=edge(x,y,c2);
    }
    sort(e1+1,e1+m+1,comp);
    sort(e2+1,e2+m+1,comp);
    for (int i=1;i<=n;i++) father[i]=i;
    for (int i=1;i<=m;i++){
        int r1=find(e1[i].x),r2=find(e1[i].y);
        if (r1!=r2){
            father[r1]=r2;++cnt;
            sum=max(sum,e1[i].w);
        }
        if (cnt==k) break;
    }
    for (int i=1;i<=m;i++){
        int r2=find(e2[i].x),r1=find(e2[i].y);
        if (r1!=r2){
            father[r1]=r2;
            sum=max(sum,e2[i].w);
        }
    }
    printf("%d\n",sum);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值