BZOJ3714 [PA2014]Kuglarz

题目描述:

魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品。花费c_ij元,魔术师就会告诉你杯子i,i+1,…,j底下藏有球的总数的奇偶性。
采取最优的询问策略,你至少需要花费多少元,才能保证猜出哪些杯子底下藏着球?

题解:

我们令sum[i]表示0~i的前缀和

那么我们想知道i~j的奇偶性只需要知道sum[j]-sum[i-1]的奇偶性即可

那么我们从i-1~j连一条边,表示要知道i~j的奇偶性的花费

最后我们要知道总花费,必须得将图联通 ,所以我们只需要在建完边的图上求出此图的最小生成树即可

因为此题是稠密图,理论上应该卡Kruskal才对,但是网上的题解大部分都用了Kruskal,数据太水。。。

prim代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[4001][4001],minn[4001];
long long ans;
bool vis[4001];
int main()
{
    scanf("%d",&n);
    n++;
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
        {
            int num;
            scanf("%d",&num);
            a[i][j]=num;
            a[j][i]=num;
        }
    for(int i=1;i<=n;i++) 
        minn[i]=a[1][i];
    minn[0]=999999999;
    vis[1]=1;
    for(int i=1;i<n;i++)
     {
        int k=0;
        for(int j=1;j<=n;j++) 
            if(!vis[j]&&minn[j]<minn[k])
                k=j;
        vis[k]=1;
        ans+=minn[k];
        for(int j=1;j<=n;j++) 
            minn[j]=min(minn[j],a[k][j]);
    }
    printf("%lld
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/jiangminghong/p/9810893.html