• 洛谷P2619 Tree I


    经典的k条白边MST

    带权二分,按照套路我们要选择尽量少的白边。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 const int N = 100010;
     5 
     6 int D;
     7 
     8 struct Edge {
     9     int x, y, val, col;
    10     inline bool operator <(const Edge &w) const {
    11         if(val - D * col == w.val - D * w.col) {
    12             return col < w.col;
    13         }
    14         return val - D * col < w.val - D * w.col;
    15     }
    16 }edge[N];
    17 
    18 int n, m, k, ans;
    19 
    20 namespace ufs{
    21     int fa[N];
    22     int find(int x) {
    23         if(x == fa[x]) {
    24             return x;
    25         }
    26         return fa[x] = find(fa[x]);
    27     }
    28     inline void merge(int x, int y) {
    29         fa[find(x)] = find(y);
    30         return;
    31     }
    32     inline bool check(int x, int y) {
    33         return find(x) == find(y);
    34     }
    35     inline void clear() {
    36         for(int i = 1; i <= n; i++) {
    37             fa[i] = i;
    38         }
    39         return;
    40     }
    41 }
    42 
    43 inline int check(int mid) {
    44     ufs::clear();
    45     D = mid;
    46     ans = 0;
    47     int cnt = 0;
    48     std::sort(edge + 1, edge + m + 1);
    49     for(int i = 1; i <= m; i++) {
    50         if(!ufs::check(edge[i].x, edge[i].y)) {
    51             cnt += edge[i].col;
    52             ans += edge[i].val - D * edge[i].col;
    53             ufs::merge(edge[i].x, edge[i].y);
    54         }
    55     }
    56     return cnt;
    57 }
    58 
    59 int main() {
    60     scanf("%d%d%d", &n, &m, &k);
    61     for(int i = 1; i <= m; i++) {
    62         scanf("%d%d%d%d", &edge[i].x, &edge[i].y, &edge[i].val, &edge[i].col);
    63         edge[i].x++;
    64         edge[i].y++;
    65         edge[i].col ^= 1;
    66     }
    67 
    68     int l = -150, r = 150;
    69     while(l < r) {
    70         int mid = (l + r + 1) >> 1;
    71         int t = check(mid);
    72         //printf("[%d %d] mid = %d cnt = %d 
    ", l, r, mid, t);
    73         if(t == k) {
    74             printf("%d
    ", ans + k * mid);
    75             return 0;
    76         }
    77         if(t < k) {
    78             l = mid;
    79         }
    80         else {
    81             r = mid - 1;
    82         }
    83     }
    84     check(r);
    85     printf("%d
    ", ans + k * r);
    86     return 0;
    87 }
    AC代码
  • 相关阅读:
    C语言ll作业01
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
    C语言寒假大作战01
    C语言I作业12—学期总结
    C语言I博客作业11
    C语言I博客作业10
    C语言I博客作业08
    C语言寒假大作战02
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10407569.html
Copyright © 2020-2023  润新知