【传送门:BZOJ3714】
简要题意:
有n个杯子,有些杯子下面有一个球,可以花费c[i][j],得到第i个杯子到第j个杯子的球的总数的奇偶性
求出知道每个杯子是否有球的最小花费
题解:
迷之最小生成树(花样玩法)
设sum[i]为1到i的球数的和
如果我们要得到i到j的奇偶性,就相当于得到了sum[j]-sum[i-1]的奇偶性
如果我们知道了所有的sum值,那么我们就可以知道每个水杯的情况(因为可以用sum[i]-sum[i-1]来得到第i个水杯的情况)
相当于所有点都在一个集合里,就是最小生成树了
对于每个条件i,j,c,就i-1向j连边,值为c
注意加long long
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> using namespace std; typedef long long LL; LL c[2100][2100]; struct node { int x,y;LL d; }a[4100000];int len; int fa[2100]; int findfa(int x) { if(x!=fa[x]) fa[x]=findfa(fa[x]); return fa[x]; } bool cmp(node n1,node n2) { return n1.d<n2.d; } int main() { int n; scanf("%d",&n); len=0; for(int i=1;i<=n;i++) { for(int j=i;j<=n;j++) { len++; a[len].x=i-1;a[len].y=j; scanf("%lld",&a[len].d); } } for(int i=0;i<=n;i++) fa[i]=i; sort(a+1,a+len+1,cmp); LL ans=0; for(int i=1;i<=len;i++) { int fx=findfa(a[i].x),fy=findfa(a[i].y); if(fx!=fy) { fa[fx]=fy; ans+=a[i].d; } } printf("%lld\n",ans); return 0; }