• BZOJ3714:[PA2014]Kuglarz(最小生成树)


    Description

    魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品。花费c_ij元,魔术师就会告诉你杯子i,i+1,…,j底下藏有球的总数的奇偶性。
    采取最优的询问策略,你至少需要花费多少元,才能保证猜出哪些杯子底下藏着球?

    Input

    第一行一个整数n(1<=n<=2000)。
    第i+1行(1<=i<=n)有n+1-i个整数,表示每一种询问所需的花费。其中c_ij(对区间[i,j]进行询问的费用,1<=i<=j<=n,1<=c_ij<=10^9)为第i+1行第j+1-i个数。

    Output

    输出一个整数,表示最少花费。

    Sample Input

    5
    1 2 3 4 5
    4 3 2 1
    3 4 5
    2 1
    5

    Sample Output

    7

    Solution

    若第$i$位的前缀和是$s[i]$,相当于要知道所有$s[i]-s[i-1]$的奇偶性。

    每次询问$[i,j]$的奇偶性,就相当于知道了$s[j]-s[i-1]$的奇偶性,就$i-1$和$j$连边,当连成一个连通块时就可以知道所有位置的奇偶性。跑一遍最小生成树就好了。

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define N (2009)
     5 using namespace std;
     6 
     7 struct Node
     8 {
     9     int x,y,v;
    10     bool operator < (const Node &a) const
    11     {
    12         return v<a.v;
    13     }
    14 }L[N*N];
    15 int n,x,cnt,fa[N];
    16 long long ans;
    17 int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);}
    18 
    19 int main()
    20 {
    21     scanf("%d",&n);
    22     for (int i=1; i<=n; ++i)
    23         for (int j=i; j<=n; ++j)
    24         {
    25             scanf("%d",&x); L[++cnt].v=x;
    26             L[cnt].x=i; L[cnt].y=j+1;
    27         }
    28     sort(L+1,L+cnt+1);
    29     for (int i=1; i<=n+1; ++i) fa[i]=i;
    30     for (int i=1; i<=cnt; ++i)
    31     {
    32         int fx=Find(L[i].x),fy=Find(L[i].y);
    33         if (fx==fy) continue;
    34         fa[fx]=fy; ans+=L[i].v;
    35     }
    36     printf("%lld
    ",ans);
    37 }
  • 相关阅读:
    LeetCode
    LeetCode
    LeetCode
    位运算实现加法运算
    反转字符串
    数组中的逆序对
    矩阵中的路径
    机器人的运动范围
    滑动窗口的最大值
    HTML5全屏浏览器兼容方案
  • 原文地址:https://www.cnblogs.com/refun/p/9887168.html
Copyright © 2020-2023  润新知