BZOJ 3714: [PA2014]Kuglarz
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1560 Solved: 758
[Submit][Status][Discuss]
Description
魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品。花费c_ij元,魔术师就会告诉你杯子i,i+1,…,j底下藏有球的总数的奇偶性。
采取最优的询问策略,你至少需要花费多少元,才能保证猜出哪些杯子底下藏着球?
Input
第一行一个整数n(1<=n<=2000)。
第i+1行(1<=i<=n)有n+1-i个整数,表示每一种询问所需的花费。其中c_ij(对区间[i,j]进行询问的费用,1<=i<=j<=n,1<=c_ij<=10^9)为第i+1行第j+1-i个数。
Output
输出一个整数,表示最少花费。
Sample Input
5
1 2 3 4 5
4 3 2 1
3 4 5
2 1
5
Sample Output
7
解题思路
首先可以知道要知道所有的至少要问n次,我们考虑加入一个0点,然后把i整体-1,之后就可以连边跑最小生成树了,否则i与i无法连边。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int MAXN = 2005;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,c[MAXN][MAXN],cnt,num;
int fa[MAXN];
LL ans;
struct Edge{
int u,v,w;
}edge[MAXN*MAXN];
int get(int x){
if(x==fa[x]) return x;
return fa[x]=get(fa[x]);
}
inline bool cmp(Edge A,Edge B){
return A.w<B.w;
}
signed main(){
// freopen("44.in","r",stdin);
n=rd();
for(register int i=1;i<=n;i++){
fa[i]=i;
for(register int j=i;j<=n;j++){
edge[++cnt].u=i-1;
edge[cnt].v=j;
edge[cnt].w=rd();
}
}
sort(edge+1,edge+1+cnt,cmp);
for(register int i=1;i<=cnt;i++){
int x=get(edge[i].u),y=get(edge[i].v);
if(x==y) continue;
num++;fa[x]=y;ans+=edge[i].w;
if(num==n) break;
}cout<<ans<<endl;
return 0;
}