zoukankan      html  css  js  c++  java
  • cogs1764 tree 最小生成树

    填坑第$n$日……链接:http://cogs.pro/cogs/problem/problem.php?pid=1764

    题意:图中有黑白双色边,要求构造出的生成树必须有恰好$need$条白色边,求出在此条件下最小生成树权值和。保证有解

    为了这道题我冒着查到被杀的风险在学校不午休逃到机房……敲了一中午再加上下午第一节课……做出来之后只能无限$orzWJMZBMR$……

    首先可以证明出来,如果给白色边权值全部加上一个定值,新生成的最小生成树中白色边的数量是不增的。我们就利用这个性质,手动给白色边全部加上一个权值,再建树,看看在这个权值下是不是可以抽出$need$条边。由于存在单调性,显然可以二分答案(加粗的字已经说明了一切)。如果这个值合法,那么就将这个情况下答案对应的白边增加的权值再减回去更新答案。

    但是这样会带来一个问题:有一些测试点,你加上$mid$数量太少,你加上$mid+1$数量又太多。这种情况下我们就要考虑$Kruskal$的原理,然后我们会发现,这种情况出现前提是:白边与黑边权值重复太多。解决办法很简单也很巧妙:把白边用黑边代替,更新答案时只减去$need$条边造成的影响即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn=50005,maxm=100005;
     7 struct node
     8 {
     9     int from,to,dis,col,next;
    10     bool operator <(const node &b)const
    11     {
    12         return dis<b.dis||(dis==b.dis&&col<b.col);
    13     }
    14 }edge[maxm];
    15 int head[maxn],tot;
    16 void addedge(int u,int v,int w,int x)
    17 {
    18     edge[++tot]=(node){u,v,w,x,head[u]};head[u]=tot;
    19 }
    20 int fa[maxn];
    21 int getfa(int x)
    22 {
    23     return fa[x]==x?x:fa[x]=getfa(fa[x]);
    24 }
    25 void unionn(int x,int y)
    26 {
    27     x=getfa(x),y=getfa(y);
    28     if(x!=y)fa[y]=x;
    29 }
    30 int n,m,need;
    31 int val;
    32 bool check(int add)
    33 {
    34     val=0;
    35     for(int i=0;i<n;i++)fa[i]=i;
    36     for(int i=1;i<=m;i++)
    37         if(!edge[i].col)edge[i].dis+=add;
    38     sort(edge+1,edge+m+1);int num=0,cnt=0;
    39     for(int i=1;i<=m;i++)
    40     {
    41         int u=edge[i].from,v=edge[i].to;
    42         if(getfa(u)!=getfa(v))
    43         {
    44             unionn(u,v);
    45             val+=edge[i].dis;
    46             if(!edge[i].col)cnt++;
    47         }
    48     }
    49     for(int i=1;i<=m;i++)
    50         if(!edge[i].col)edge[i].dis-=add;
    51     return cnt>=need;
    52 }
    53 int haha()
    54 {
    55     freopen("nt2012_tree.in","r",stdin);
    56     freopen("nt2012_tree.out","w",stdout);
    57     scanf("%d%d%d",&n,&m,&need);
    58     for(int i=1;i<=m;i++)
    59     {
    60         int u,v,w,x;scanf("%d%d%d%d",&u,&v,&w,&x);
    61         addedge(u,v,w,x);
    62     }
    63     int l=-105,r=105,mid,query;
    64     while(l<=r)
    65     {
    66         mid=(l+r)>>1;
    67         if(check(mid))l=mid+1,query=val-mid*need;
    68         else r=mid-1;
    69     }
    70     printf("%d
    ",query);
    71 }
    72 int sb=haha();
    73 int main(){;}
    cogs1764
  • 相关阅读:
    2:编写虚幻引擎中的UC和C++代码
    1:编写虚幻引擎中的UC和C++代码
    0:编写虚幻引擎中的UC和C++代码
    4:虚幻引擎网络架构:技术要点总结篇
    3:虚幻引擎网络架构:GameInfo,PlayerMove
    2:虚幻引擎网络架构:Replication
    1:虚幻引擎网络架构:Actors
    R12-表详解-总帐
    clob 类型
    成本更新和算法
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7354699.html
Copyright © 2011-2022 走看看