zoukankan      html  css  js  c++  java
  • 小火山的宝藏收益 多校训练2(小火山专场) poj(邻接表+DFS)

    http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1907

    Description
    
      
      进去宝藏后, 小火山发现宝藏有N个房间,且这n个房间通过N-1道门联通。
      每一个房间都有一个价值为Ai的宝藏, 但是每一个房间也都存在一个机关。如果小火山取走了这个房间的宝藏,那么这个房间通往其他房间的门就永远打不开了,也就是说后面的宝藏小火山是得不到了(进入这个房间的门是不会关闭的,小火山还是可以回去的);如果小火山不取这个宝藏,而是去打开通往另一房间的门,那么这个房间的宝藏就会消失, 小火山就得不到这个房间的宝藏。
      不过,小火山已经有了藏宝图,知道每一个房间的宝藏的价值,现在想请你帮小火山算一下,他最多能获得多少钱去买股票?
    Input
    
    输入第一行是一个整数T(T <= 50), 表示一共有T组数据。
    对于每一组数据,第一行是两个数N, S(1 <= N <= 10000, 1 <= S <= N), N代表有N个房间, S代表小火山进去宝藏后的
    起始房间(小火山怎么进入起始房间不重要),第二行是N个数,代表每个房间宝藏的价值, 随后N-1行, 每行两个数A, B, 代表
    A, B这两个房间联通。
    Output
    
    对于每一组数据输出一个整数, 代表小火山能获得的最大钱数。
    
    Sample Input
    
    2
    1 1
    20
    3 1
    4 5 6
    1 2
    2 3
    Sample Output
    
    20
    6
    

      

    分析:一开始比较纠结到底要怎么处理取该房间宝藏其他房间门就关闭这一点。后来想通了。。

    举例子来说,取一个点,把与之相邻的点的和加一起与这个点本身的值进行比较,哪个大取哪个即可。(简单的例子,与之相邻的点都没有其他相邻的点了)

    若与之相邻的点还有其他的点,那么方法还是一样,按照这个方法进行递归即可。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <stack>
    #include <math.h>
    
    using namespace std;
    
    #define met(a, b) memset(a, b, sizeof(a))
    #define maxn 11000
    #define INF 0x3f3f3f3f
    const int MOD = 1e9+7;
    
    typedef long long LL;
    int cnt, head[maxn], v[maxn], value[maxn];
    
    struct node
    {
        int u, v, next;
    }maps[4*maxn];
    
    void Add(int u, int v)
    {
        maps[cnt].v = v;
        maps[cnt].next = head[u];
        head[u] = cnt ++;
    }
    
    int DFS(int s)
    {
        int sum = 0;
        for(int i=head[s]; i!=-1; i=maps[i].next)
        {
            int p = maps[i].v;
            if(!v[p])
            {
                v[p] = 1;
                sum += DFS(p);
            }
        }
        
        return max(sum, value[s]);
    }
    
    int main()
    {
        int T, a, b, s, n;
    
        scanf("%d", &T);
    
        while(T --)
        {
            scanf("%d %d", &n, &s);
    
            for(int i=1; i<=n; i++)
                scanf("%d", &value[i]);
    
            memset(head, -1, sizeof(head));
            cnt = 0;
    
            for(int i=1; i<n; i++)
            {
                scanf("%d %d", &a, &b);
                Add(a, b);
                Add(b, a);
            }
    
            memset(v, 0, sizeof(v));
            v[s] = 1;
    
            int ans = DFS(s);
    
            printf("%d
    ", max(ans, value[s]));
    
        }
        return 0;
    }
    
    
    /*
    1
    5 2
    5 5 2 1 5
    1 5
    1 2
    2 3
    2 4
    */
    View Code
  • 相关阅读:
    hdu1565 用搜索代替枚举找可能状态或者轮廓线解(较优),参考poj2411
    cf1114D 区间dp基础
    poj2411 状态压缩-铺地板题型-轮廓线解法(最优)
    poj3254 炮兵阵地弱化版,记数类dp
    poj2441状态压缩dp基础
    zoj3471 状态压缩dp基础
    北极通讯网络(最小生成树)
    黑暗城堡(生成树)
    关押罪犯(并查集)
    搭配购买(并查集+0/1背包)
  • 原文地址:https://www.cnblogs.com/daydayupacm/p/5760108.html
Copyright © 2011-2022 走看看