题解:
参考小胖的奇偶那道题。
那道题用的并查集维护。
如果知道 i..j 之间奇偶性的话,实际上知道的是 sum[j]-sum[i-1]的奇偶性(sum为前缀和)。
可以用扩展域的并查集维护任意两个sum[i]之间的差值。
有了这个结论,如果全部知道哪些杯底有球,就需要所有的sum之间的关系已知,也就是并查集中所有点都在一个集合中,是一棵树。
所以遍转化成了最小生成树问题。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
//by zrt
//problem:
using namespace std;
int n;
struct N{
int x,y,w;
}map[2005*2005];
int tot;
bool cmp(N a,N b){
return a.w<b.w;
}
int f[2005];
int get(int x){
return f[x]==x?x:f[x]=get(f[x]);
}
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
scanf("%d",&map[tot].w);
map[tot].x=i;
map[tot].y=j+1;
tot++;
}
}
sort(map,map+tot,cmp);
long long cost(0);
for(int i=1;i<=n+1;i++) f[i]=i;
for(int i=0;i<tot;i++){
if(get(map[i].x)!=get(map[i].y)){
f[get(map[i].x)]=get(map[i].y);
cost+=map[i].w;
}
}
printf("%lld\n",cost);
return 0;
}