【p1268 树的重量】
先做一个约定[i,j]表示从i到j的距离我们可以先从n=2,也
就是最简单的情况来切入这道题对于n=2,答案显然是[1,2]
考虑n=3,三这个节点一定是插在1与2两个节点之间的我们可以发现,3节点的插入使得,树的权值增加了([1,3]+[2,3]-[1,2])/2 (即紫线与蓝线的权值和减去绿线除以二)我们可以把这个权值贡献的式子,推广到一般情况,即x节点插入在[i,j]路径上,其对答案的贡献为([i,x]+[j,x]-[i,j])/2
可以发现我们紫色的那个其实是重复枚举,因为[1,4]+[3,4]-[1,3] 和[2,4]+[3,4]-[2,3] 其实都是一样的。这个结论也可以推广至一般状况中所以说我们完全可以省去枚举中的一维只枚举1~n就好
#include<iostream>
#include<cstdio>
using namespace std;
long long read()
{
long long x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int N=30+5;
int n,a[N][N];
int main()
{
while(1)
{
memset(a,0,sizeof a);
int ans=0;
n=read();
if(n==0) break;
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
a[i][j]=a[j][i]=read();
ans+=a[1][2];
for(int i=3;i<=n;i++)
{
int t_ans=0x3f3f3f3f;
for(int j=1;j<i;j++)
for(int k=1;k<j;k++)
t_ans=min(t_ans,(a[j][i]+a[k][i]-a[j][k])/2);
ans+=t_ans;
}
printf("%d\n",ans);
}
return 0;
}