zoukankan      html  css  js  c++  java
  • ACM-Divide Tree

    题目描述:Divide Tree
     

    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
    

    样例输出

    2

    DFS水题

    备注:另一个结点的权值=父节点权值-当前结点的权值。

    //// Divide Tree.cpp : 定义控制台应用程序的入口点。
    ////
    //
    //#include "stdafx.h"
    //
    //#include <stdio.h>
    //#include <string.h>
    //#include <cmath>
    //#include <iostream>
    //using namespace std;
    //
    //const int maxn = 10005;
    //const int INF = 0x3f3f3f3f;
    //
    //int t, n, graph[maxn][maxn],weight[maxn],vis[maxn];
    //int ans,sum[maxn];
    //
    //
    ////计算子树权值
    ////思路:沿着DFS路线就可以确定树的权值
    //void sum_weight(int i)
    //{
    //    vis[i] = 1;
    //
    //    sum[i] = weight[i];
    //
    //    for (int j = 1; j <= n; j++)
    //    {
    //        if (!vis[j] && graph[i][j])//沿着边搜索没有经过的顶点
    //        {
    //            sum_weight(j);
    //            sum[i] += sum[j];
    //        }
    //    }
    //}
    //
    //
    //
    //void DFS(int i)
    //{
    //    vis[i] = 1;
    //    
    //    for (int j = 1; j <= n; j++)
    //    {    
    //        if (graph[i][j] && !vis[j])//也是沿着边搜索
    //        {
    //            //思路:
    //            //1.一个顶点的权值:s[j]
    //            //2.另一个顶点的权值:s[i] - s[j]
    //            int sub_diff = (sum[i] - sum[j]) - sum[j];
    //            ans = ans < abs(sub_diff) ? ans : abs(sub_diff); 
    //            DFS(j);
    //        }
    //    }
    //}
    //
    //int main()
    //{
    //    scanf("%d",&t);
    //    while (t--)
    //    {
    //        memset(graph, 0, sizeof(graph));
    //        memset(vis, 0, sizeof(vis));
    //        scanf("%d", &n);
    //        for (int i = 1; i <= n; i++)
    //        {
    //            scanf("%d", &weight[i]);
    //        }
    //        for (int i = 1; i <= n-1; i++)
    //        {
    //            int v1, v2;
    //            scanf("%d %d", &v1, &v2);
    //            graph[v1][v2] = 1;
    //            graph[v2][v1] = 1;//无向图!!!!
    //        }
    //
    //        sum_weight(1);
    //        
    //        ans = INF;
    //        memset(vis, 0, sizeof(vis));
    //        DFS(1);
    //        
    //        printf("%d
    ",ans);
    //
    //    }
    //    return 0;
    //}
    //
    
    #include "stdafx.h"
    #include <stdio.h>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <string.h>
    using namespace std;
    
    const int M = 10005;
    const int INF = 0x3f3f3f3f;//c、c++的最大数是十六进制的0x
    
    int t, n,ans,weight[M],vis[M],sum[M];
    vector<int> G[M];
    
    void sum_weight(int i)
    {
        vis[i] = 1;
    
        sum[i] = weight[i];
    
        for (int j = 0; j < G[i].size(); j++)
        {
            int next = G[i][j];
    
            if (!vis[next])//沿着边搜索没有经过的顶点
            {
                sum_weight(next);
                sum[i] += sum[next];
            }
        }
    }
    
    void DFS(int i)
    {
        vis[i] = 1;
        
        for (int j = 0; j < G[i].size(); j++)//直接遍历边比遍历顶点循环次数少,可以达到减枝的目的。
        {    
            int next = G[i][j];
            if (!vis[next])//也是沿着边搜索
            {
                //思路:
                //1.一个顶点的权值:s[j]
                //2.另一个顶点的权值:s[i] - s[j]
                int sub_diff = (sum[1] - sum[next]) - sum[next];//为什么这里是sum[1]-sum[j],不是sum[i]-sum[j]????
                ans = ans < abs(sub_diff) ? ans : abs(sub_diff); 
                DFS(next);
            }
        }
    }
    
    int main()
    {
    
        scanf("%d",&t);
        while (t--)
        {
            memset(vis, 0, sizeof(vis));
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
            {
                scanf("%d", &weight[i]);
                G[i].clear();
            }
            for (int i = 1; i <= n - 1; i++)
            {
                int v1, v2;
                scanf("%d %d", &v1, &v2);
                G[v1].push_back(v2);
                G[v2].push_back(v1);
            }
    
            sum_weight(1);
    
            ans = INF;
            memset(vis, 0, sizeof(vis));
            DFS(1);
    
            printf("%d
    ", ans);
    
        }
        
    
        return 0;
    }
  • 相关阅读:
    软件需求,概要设计,详细设计(文档)
    需求文档和设计文档的区别
    Sqlyog和Navicat——mysql数据库图像化管理工具,
    Sqlyog 和Navicat
    端口占用问题
    List集合
    JSON——(JavaScript Object Notation, JS 对象简谱) 数据交换格式。JSON是一个序列化的对象或数组。
    Excel图表导出高清矢量位图片并裁剪的方法
    使用福昕PDF编辑器裁剪PDF页面
    Latex模板默认两栏的分栏的情况下怎么让图片和表格占一栏显示
  • 原文地址:https://www.cnblogs.com/x739400043/p/8505474.html
Copyright © 2011-2022 走看看