LuoguP1268树的重量【构造/思维】By cellur925

题目传送门

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\n",ans);
26         ans=0;
27         memset(f,0,sizeof(f));
28     }
29     return 0;
30 }
View Code

猜你喜欢

转载自www.cnblogs.com/nopartyfoucaodong/p/9781581.html
今日推荐