10.16T4 GCD递归

Description

  天平的两边有时不一定只能挂物品,还可以继续挂着另一个天平,现在给你一些天平的情况和他们之间的连接关系,要求使得所有天平都能平衡所需物品的总重量最轻,一个天平平衡当且仅当“左端点的重量*左端点到支点的距离=右端点的重量*右端点到支点的距离”。注意题目中的输入保证这些天平构成一个整体。

Input

  第一行包含一个N(N<=100),表示天平的数量,,天平编号为1到N,接下来包含N行描述天平的情况,每行4个整数P,Q,R,B,P和Q表示横杆上支点到左边的长度与到右边的距离的比例为P:Q,R表示左边悬挂的情况,如果R=0说明悬挂的物品,否则表示左边悬挂的是天平R;B表示右边的悬挂情况,如果B=0表示右边悬挂的是物品,否则右边悬挂着天平B。
  对于所有的输入,保证W*L<2^31,其中W为最轻的物品重量,而L为输入中描述左右比例时出现的最大值。

Output

  输出一个整数表示使得所有天平都平衡所需最轻的物品总重量。

Sample Input

4
3 2 0 4
1 3 0 0
4 4 2 1
2 2 0 0

Sample Output

40

Hint

      
 
 
 
 
 
 
 
如果我们一个天平的两边的所有天平都平衡了,现在我们要调平这个天平。
假设重量是W1,W2,左右两臂长度是L1,L2,我们要把第一个重量放大X倍,第二个放大Y倍
则明显我们就有X*W1*L1=Y*W2*L2
现在我们肯定要求X与Y的最小比值才能保证所有的重量是最小的
我们显然有式子
显然我们要求比值就可以求W2*L2与W1*L1的最大公约数,X=W2*L2/gcd,Y=W1*L1/gcd
然后递归回去就可以了
如果我们遇到空节点就直接返回1,显然
注意1号杠杆并不一定是最上面的杠杆,所以我们要记录一下父亲关系找到最上面的杆子
code:
 1 #include<iostream>
 2 #include<cstdio>
 3 #define N 100006 
 4 using namespace std;
 5 int gcd(int a,int b){
 6     if(a<b)swap(a,b);
 7     while(a=a%b)swap(a,b);
 8     return b;
 9 }
10 int lcm(int a,int b){
11     return a/gcd(a,b)*b;
12 }
13 struct node{
14     int P,Q,L,R,W;
15 }e[N];
16 int dfs(int x){
17     if(x==0)return 1;
18     int left=dfs(e[x].L),right=dfs(e[x].R);
19     int p=gcd(e[x].P*left,e[x].Q*right);
20     int X=e[x].P*left/p,Y=e[x].Q*right/p;
21     return X*right+Y*left;
22 }
23 int fa[N];
24 int main(){
25     int n;
26     cin>>n;
27     for(int i=1;i<=n;i++)fa[i]=i;
28     for(int i=1;i<=n;i++){
29         int P,Q,L,R;
30         cin>>e[i].P>>e[i].Q>>e[i].L>>e[i].R;
31         fa[e[i].L]=i,fa[e[i].R]=i;
32     }
33     int root=0;
34     while(fa[root]!=root){
35         root=fa[root];
36     }
37     cout<<dfs(root);
38     return 0;
39 }

over

 
posted @ 2018-10-16 18:43  saionjisekai  阅读(94)  评论(0编辑  收藏  举报