[swustoj 785] Divide Tree

Divide Tree(0785)

问题描述

As we all know that we can consider a tree as a graph. Now give you a tree with nodes having its weight. We define the weight of a tree is the sum of the weight of all nodes on it. You know we can divide the tree into two subtrees by any edge of the tree. And your task is to tell me the minimum difference between the two subtrees’ weight.

输入

The first line, an integer T (T <= 30), representing T test cases blew.

For each test case, the first line contains one integer N (2 <= N <= 10000), indicating the number of tree’s nodes. Then follow N integers in one line, indicating the weight of nodes from 1 to N.

For next N-1 lines, each line contains two integers Vi and Vj (1 <= Vi, Vj <= N), indicating one edge of the tree.

输出

For each test case, output the minimum weight difference. We assume that the result will not exceed 2^20.

样例输入

1
5
6 3 9 3 1
2 3
3 1
4 1
1 5

样例输出

20

简单题

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
#define min(a,b) ((a)<(b)?(a):(b))
#define INF 0x3f3f3f3f
#define pb push_back
#define N 10010
 
int n;
int ans;
int val[N];
int size[N];
vector<int> edge[N];
 
 
void init()
{
    ans=INF;
    for(int i=1;i<=n;i++){
        edge[i].clear();
        size[i]=0;
    }
}
void dfs1(int u,int pre)
{
    size[u]=val[u];
    for(int i=0;i<edge[u].size();i++){
        int v=edge[u][i];
        if(v!=pre){
            dfs1(v,u);
            size[u]+=size[v];
        }
    }
}
void dfs2(int u,int pre)
{
    for(int i=0;i<edge[u].size();i++){
        int v=edge[u][i];
        if(v!=pre){
            ans=min(ans,abs((size[1]-size[v])-size[v]));
            dfs2(v,u);
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
        }
        for(int i=1;i<n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            edge[a].pb(b);
            edge[b].pb(a);
        }
        dfs1(1,1);
        dfs2(1,1);
        printf("%d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/hate13/p/4605223.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值