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\n",ans); return 0; }