ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BZOJ 3714 Kuglarz

2022-02-04 17:33:08  阅读:145  来源: 互联网

标签:3714 方程 连边 int mid Kuglarz 我们 wy BZOJ


BZOJ 3714 Kuglarz

非常玄学的一道题....到现在还没理解为什么是最小生成树的题...
这里就从另一个角度解析题目,首先题目中每个杯子中是否藏有球可以视为0/1,而我们询问的一个区间的奇偶可以看做是若干个变量相异或的和,而每个变量的意义就是该杯子下是否藏有求0/1.那么我们的目的是想知道这n个变量的值,根据线性代数的一些知识,我们知道解出n个变量的唯一解的冲要条件是有n个本质上不同的方程(其实这也可以通过手玩样例来得出)。那我们怎么来选出这n个方程,并且维护他们是否已经被已有的方程给生成了。我们可以举个例子就能简单的判断,第一个方程:l-mid,第二个方程mid+1,r,第三个方程,l,r。显然第三个方程可以被前两个方程相加得到。维护关系的话我们很容易想到的就在边界处两边,可直接在l-mid,和mid+1-r连边,无法看出l和r的关系。同时我们发现只有相邻的时候才会合并,那我们将l-mid+1连边,mid+1-r连边即可。这样的话l-r就联通,说明l-r这个区间就不行了。那我们知道最后n个方程,即n个边最后的结果就是1到n+1的一个最小生成树。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2010;
int n,f[N],num;
struct wy{int x,y,v;}a[N*N*2]; 
inline int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);}
inline bool cmp(wy a,wy b){return a.v<b.v;}
inline void kruskal()
{
    sort(a+1,a+num+1,cmp);
    for(int i=1;i<=n+1;++i) f[i]=i;
    int cnt=0;
    ll ans=0;
    for(int i=1;i<=num;++i)
    {
        int t1=getf(a[i].x),t2=getf(a[i].y);
        if(t1!=t2)
        {
            f[t1]=t2;
            ans+=a[i].v;
            if(++cnt==n) break;
        }
    }
    printf("%lld",ans);
}
int main()
{
//    freopen("1.in","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        for(int j=i;j<=n;++j)
        {
            int x;scanf("%d",&x);
            a[++num].x=i;a[num].y=j+1;
            a[num].v=x;
        }
    kruskal();    
    return 0;
} 

标签:3714,方程,连边,int,mid,Kuglarz,我们,wy,BZOJ
来源: https://www.cnblogs.com/gcfer/p/15863093.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有