P5994 [PA2014]Kuglarz(思维 最小生成树)

P5994 [PA2014]Kuglarz(思维 最小生成树)

题意:

​ 你可以询问[l,r]区间的杯子下球的总数的奇偶性,花费是costi,j(ij)。若想要知道每个杯子下有无球,求最小花费是多少。杯子的数量为2e3

思路:

​ 很容易知道,若想要知道第i个杯子下面有没有球,有两种方式。1.直接询问[i,i]。2.询问[i,j]+[i+1,j][j,i]+[j,i1]

​ 那就能想到一个很暴力的方法,也就是区间DP(n ^ 3)。不过复杂度过高,不可写。

​ 现在假设一个超级源点0,[0, 0]是没有球的。如果我们知道所有的[0,i](1in),就可以知道每个位置有无小球。由于上面的结论, 我们可以知道,如果我们知道了[0,i1][i,j]的奇偶性,就可以知道[0,j]的奇偶性。同理,知道[0,j][i,j]就可以知道[0,i1]

​ 所以,对于区间[a,b],我们可以将[0,a1][0,b]之间连一条权值为costa,b的边,表示我知道了这两点中的一个,就可以花费costa,b得到另一个。如果我们想要知道所有的杯子下有无球,那就需要知道[0,i](in),也就是整个图联通。

​ 我们按上述做法建图,跑一个裸的最小生成树就可以了。

实现:

#include <bits/stdc++.h>

using namespace std;
#define int long long

const int N = 2005, M = N * N / 2;
int n;
int cost[N][N];
int res;

struct node {
    int l, r, cost;
    bool operator < (const node &a) const {
        return cost < a.cost;
    }
} edges[M];
int idx = 0;
int fa[N];

int fd(int x)   
{
    if(fa[x] != x)  fa[x] = fd(fa[x]);
    return fa[x];
}

void kruskal()
{
    int cnt = 0;
    res = 0;
    for(int i = 1; i <= idx; i ++)
    {
        auto [a, b, w] = edges[i];
        int ta = fd(a), tb = fd(b);
        if(ta == tb)    continue;
        fa[tb] = ta;
        res += w, cnt ++;
        if(cnt == n)    break;
    }
}

signed main()
{
    scanf("%lld", &n);
    for(int i = 1; i <= n; i ++)    fa[i] = i;
    for(int i = 1; i <= n; i ++)
        for(int j = i; j <= n; j ++)
        {
            scanf("%lld", &cost[i][j]);
            edges[++ idx] = {i - 1, j, cost[i][j]};
        }

    sort(edges + 1, edges + idx + 1);
    kruskal();
    printf("%lld\n", res);
}
posted @   DM11  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
主题色彩
点击右上角即可分享
微信分享提示