BZOJ3714: [PA2014]Kuglarz

【传送门: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;
}

 

posted @ 2018-03-21 11:23  Star_Feel  阅读(128)  评论(0编辑  收藏  举报