【BZOJ3714】【PA2014】Kuglarz(最小生成树)

来源:互联网 发布:javascript 获取位置 编辑:程序博客网 时间:2024/06/06 20:44

题目描述:Kuglarz 传送门


算法:

最小生成树(藏得很深)

把缝当做点,费用作为边的权值,求最小生成树。


做法:


刚看这道题,觉得毫无思路,每个区间都可以询问,但只告诉奇偶性,这怎么办?

进一步分析,我们发现,如果要知道一个位置到底有没有球,就只能能知道他的奇偶性才行,你询问的范围 l 必须等于 r 才行。

然后我们发现答案是可以传递的:如果我们想知道 [ a, b ] 的奇偶,我们通过可以知道 [ a , c ] 和 [ c , b ] 来推导出。最终我们是要知道每一个 [ a , a ] 的。

网上的题解告诉我:把杯子之间的缝当成点,当询问一个区间时,就把区间两边的缝连起来,求最小生成树。仔细想想,一个树上的点可以到达树上的任意一个点,这不就是运用了答案的传递性吗!啊啊啊,忒强!


#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;inline void getint(int &x){x=0; char c = getchar();while(!(c>='0'&&c<='9')) c=getchar();while(c>='0'&&c<='9') x=x*10+c-'0', c=getchar();}typedef long long LL;const int N=2010;int n, mi;int fa[N];struct Edge{int u,v,w;bool operator < (const Edge & rhs)const{return w<rhs.w;}}e[N*N>>1];inline void add(int i,int j,int w){e[++mi] = (Edge){i,j,w};} int find(int x){if(fa[x]==x) return x;else fa[x]=find(fa[x]);}int main(){scanf("%d",&n);for(int i=0, j, w; i<n; ++i) for(j=i+1; j<=n; ++j){getint(w); add(i,j,w);}LL ans=0;int tot=0;sort(e+1,e+mi+1);for(int i=0; i<=n; ++i) fa[i]=i;for(int i=1, u, v; i<=mi; ++i){u = e[i].u; v = e[i].v;if(find(u)!=find(v)){ans += e[i].w;fa[find(u)]=find(v);if(++tot==n) break;}}printf("%lld\n",ans);return 0;}



原创粉丝点击