Description
给你一个矩阵$M$,$M(i,j)$表示$i$到$j$的最短距离。定义树的重量为树上各边权之和,对于任意给出的合法矩阵$M$,已知它所能表示树的重量是唯一确定的。给出一个矩阵,求它所表示的树的重量。
Sol
这道题我想了一会发现什么思路都没有...然后企图画一点图也无济于事...
后来看题解发现我们其实可以从简单的角度入手,逐渐发现规律。
当有两个点的时候,显然答案就是$g(1,2)$。
当有三个点的时候,如图,发生了分叉。(因为各点都是叶子节点)
(图片引用自 @TsReaper)
设蓝线部分为$len$,那么树的重量就是$g(1,2)$+$len$。那么$len$部分怎么求?稍微想想可以得出$len=g(1,3)+g(2,3)-g(1,2)$再除以2。
类比一下,当有四个...五个...六个...点的时候,也会在某一个路径上发生分叉,而一个点只可能从在它编号之前的点分叉而来。于是我们对于每个点,枚举一下它是从它之前哪个点分叉过来的,取个最小值累加即可得到答案。
Code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 7 int n,ans; 8 int f[50][50]; 9 10 int main() 11 { 12 while(scanf("%d",&n)!=EOF&&n) 13 { 14 for(int i=1;i<=n-1;i++) 15 for(int j=i+1;j<=n;j++) 16 scanf("%d",&f[i][j]),f[j][i]=f[i][j]; 17 ans+=f[1][2]; 18 for(int i=3;i<=n;i++) 19 { 20 int tmp=0x3f3f3f3f; 21 for(int j=2;j<=i-1;j++) 22 tmp=min(tmp,(f[1][i]-f[1][j]+f[i][j])>>1); 23 ans+=tmp; 24 } 25 printf("%d ",ans); 26 ans=0; 27 memset(f,0,sizeof(f)); 28 } 29 return 0; 30 }