Logo S08577 的博客

博客

P5687 [CSP-S2019 江西] 网格图

...
S08577
2025-12-01 12:57:33

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2025-10-16 08:27:11

好题。

从kruscal的本质出发,我们是贪心连权值最小的边,如果出现环那么这条边就不连。

这道题也是类似,贪心考虑,不出现环的情况下,肯定是把一行或者一列全部连起来,代价是 $w*(n-1)$

但是如果出现环怎么办,考虑什么时候会出现环,当我们连的行数和列数都大于等于2时,会出现环。因为我们贪心连边,所以删边肯定是删当前边而不是前面的边。

考虑会删几条边,肯定是连了这一列或一行多出现的环,以连了一列为例,那么多出的环肯定是 连的行数 减一。因为考虑我们连的第一条行与第一条列是不被删除的,所以我们只要再连就肯定会出现新环。

所以少的代价就是 $(y-1) \times a[i].x$。

行同理。

代码

struct node{
    int x;
    int id;
}a[N];
bool cmp(node a,node b){
    return a.x<b.x;
}
signed main(){
    
\/\/   freopen("a.in","r",stdin);
\/\/   freopen("a.out","w",stdout);
    fst
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        cin>>a[i].x;
        a[i].id=1;
    }
    for(int i=n+1;i<=n+m;i++) {
        cin>>a[i].x;
        a[i].id=2;
    }
    sort(a+1,a+1+n+m,cmp);
    int x=0,y=0;
    int res=0;
    for(int i=1;i<=n+m;i++){
        if(a[i].id==1){
            res+=a[i].x*(m-1);
            if(x<n) x++;
            else x=n;
            if(x>=2&&y>=2) res-=(y-1)*a[i].x;
        }
        if(a[i].id==2){
            res+=a[i].x*(n-1);
            if(y<m) y++;
            else y=n;
            if(x>=2&&y>=2) res-=(x-1)*a[i].x;
        }
    }
    cout<<res<<endl;
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。