• LOJ10069 TREE


    题目描述

    原题来自:2012 年国家集训队互测

    给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有 need 条白色边的生成树。题目保证有解。

    输入格式

    第一行 V,E,need 分别表示点数,边数和需要的白色边数。

    接下来 E 行,每行 s,t,c,col 表示这边的端点(点从 0 开始标号),边权,颜色( 0白色,1 黑色)。

    输出格式

    一行表示所求生成树的边权和。

    样例

    样例输入

    2 2 1
    0 1 1 1
    0 1 2 0
    

    样例输出

    2
    

    数据范围与提示

    对于所有数据,V<=5e4,E<=1e5边权为 [ 1,100 ] 中的正整数。

    ___________________________________________________

    想要加入的边数刚好是need条,需要在边上附加权值,控制加入的多少。

    所以二分增加的权值,让后最小生成树。

    本来很简单,但是刚开始的方法是当条数为need时统计加权以前的边的权值之和,这样会出现所有白边黑白等长而由于白边在前,从而无法取到黑边,白边又超过need的情况,无法解决。所以改为统计加权前的边的和再减去增加权乘以need的积,答案正确。为什么need条数不对还正确呢?因为黑白边等长!!!

    ___________________________________________________

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=5e4+10;
     4 const int maxm=1e5+10;
     5 int n,m,need;
     6 struct edge
     7 {
     8     int u,v,w,ww,c;
     9 }e[maxm];
    10 bool cmp(edge a,edge b)
    11 {
    12     return a.ww==b.ww?a.c<b.c:a.ww<b.ww;
    13 }
    14 int fa[maxm];
    15 int find(int x)
    16 {
    17     return fa[x]==x?x:fa[x]=find(fa[x]);
    18 }
    19 int ans;
    20 int pd(int x)
    21 {
    22     for(int i=0;i<m;++i)e[i].ww=e[i].w+(e[i].c==0?x:0);
    23     sort(e,e+m,cmp);
    24     for(int i=1;i<=n;++i)fa[i]=i;
    25     ans=0;
    26     int cntb=0,cnt=0;
    27     for(int i=0;i<m;++i)
    28     {
    29         int a=find(e[i].u),b=find(e[i].v);
    30         if(a!=b)
    31         {
    32               cnt++;
    33             ans+=e[i].ww;
    34             fa[a]=b;
    35             if(e[i].c==0)cntb++;
    36               if(cnt==n-1)break;
    37         }
    38     }
    39     return cntb;
    40 }
    41 int da;
    42 int main()
    43 {
    44     scanf("%d%d%d",&n,&m,&need);
    45     for(int i=0;i<m;++i)
    46     {
    47         scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].w,&e[i].c);
    48         e[i].u++;
    49         e[i].v++;
    50     }
    51     int l=-101,r=101;
    52     while(l<=r)
    53     {
    54         int mid=(l+r)>>1,tf=pd(mid);
    55         if(tf>=need)
    56         {
    57             l=mid+1;
    58             da=ans-need*mid;
    59         }
    60         else
    61         {
    62             r=mid-1;
    63         }
    64     }
    65     cout<<da;
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    C# 设置 Excel 条件格式 与 冻结窗口
    Exce折叠效果(数据组合)
    [一点一滴学英语]20050829
    Tencent Messenger
    很有趣的一篇文章:不使用Linux的五大理由
    Tencent Messenger (continued)
    N久没有听过这么搞笑的RAP了
    [一点一滴学英语]20050827
    [Eclipse笔记]SWT真正的优势不是快这么简单
    [一点一滴学英语]20050828
  • 原文地址:https://www.cnblogs.com/gryzy/p/11450877.html
Copyright © 2020-2023  润新知