bzoj3714 [PA2014]Kuglarz

Captain_Paul

2018-09-26 18:42:16

Personal

题意:$n$个杯子依次编号$1$到$n$,某些杯子下面有一个小球,可以询问区间$[l,r]$中小球数量的奇偶性,花费$c_{l,r}$,问要知道所有小球的分布情况的最少花费 ------------ 询问一个区间$[l,r]$,可以看作在$l-1$和$r$之间连边 最终要使得图连通,最小花费就是最小生成树的大小 ``` #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define reg register using namespace std; typedef long long ll; const int N=2005; struct E { int from,to,dis; inline friend bool operator < (E a,E b) {return a.dis<b.dis;} }e[N*N]; int n,m,f[N]; inline int read() { int x=0,w=1; char c=getchar(); while (!isdigit(c)&&c!='-') c=getchar(); if (c=='-') c=getchar(),w=-1; while (isdigit(c)) { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return x*w; } int find(int x){return f[x]==x?x:f[x]=find(f[x]);} inline ll Kruskal(ll res=0) { sort(e+1,e+m+1); for (reg int i=1;i<=n;i++) f[i]=i; for (reg int i=1,cnt=0;i<=m;i++) { int u=find(e[i].from),v=find(e[i].to); if (u==v) continue; f[u]=v; res+=e[i].dis; } return res; } int main() { n=read(); for (reg int i=1;i<=n;i++) for (reg int j=i;j<=n;j++) e[++m]=(E){i-1,j,read()}; printf("%lld\n",Kruskal()); return 0; } ```