codeforces 842C Ilya And The Tree (01背包+dfs)

(点击此处查看原题)

题目分析

题意:在一个树中,有n个结点,记为 1~n ,其中根结点编号为1,每个结点都有一个值val[i],问从根结点到各个结点的路径中所有结点的值的gcd(最大公约数)最大是多少,其中,我们可以将路径中某一个结点的值变为0,也可以选择不变。

思路:注意到对于每个结点,我们可以选择这个结点,或者不选这个结点(将权值记为0),因而有点01背包的感觉,而我们求gcd的时候需要取所有情况中的最大值

那么我们从根结点开始,每经过一个结点,就从其父节点的所有情况转移得到当前结点的状态,而对于每个结点所含有的状态,有如下三种

1)从根结点到当前结点,没有将任一结点的值变为0的情况下得到的gcd

2)从根结点到当前结点,选取除当前结点外的所有结点得到的gcd,也就是将当前结点的值当作0

3)由其父节点的所有情况转移而来,由于父节点的情况中一定会有不选取从根结点到父节点途中某点的情况,那么我们由父结点向当前结点转移得到的gcd(当前结点的值不当作0),代表不选取根结点到当前结点途中某点的情况。

这三种情况实际上整合为两种情况,即是由父结点转移到当前点的过程中,是否选择当前结点的两种情况,不过有的情况下我们必须选取当前结点,所以为了避免这种麻烦的判断,写为三种情况。

最后,我们取每个点所有情况下的最大值即可,不过为了节省时间和空间,我们用set对每个结点的状态去重。

(吐槽:个人感觉这种写法有TLE的嫌疑,又或者这个题的数据有点水....)

代码区

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>
#include<set>
#include<cmath>

#define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 998244353;
const int Max = 2e5 + 10;
const int Max2 = 1e3 + 10;

struct Edge
{
    int to, next;
} edge[Max << 1];

int n;
int head[Max], tot;
int val[Max], beauty[Max];
set<int> s[Max];

void init()
{
    memset(head, -1, sizeof(head));
    tot = 0;
    for (int i = 1; i <= n; i++)
        s[i].clear();
}

void add(int u, int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

int gcd(int a, int b)
{
    if (a < b)
        swap(a, b);
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

void dfs(int u, int fa, int now)
{
    for (auto it:s[fa])
    {
        s[u].insert(gcd(it, val[u]));       //选取当前数,更新由父结点转移来的所有情况
    }
    s[u].insert(now);                          //不选当前结点
    now = gcd(now,val[u]);                  //now代表的是没有删除任何点的情况下的gcd
    s[u].insert(now);                          //不删除任何点

    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (v == fa)
            continue;
        dfs(v, u, now);
    }
}

int main()
{
#ifdef LOCAL
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    while (scanf("%d", &n) != EOF)
    {
        init();
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", val + i);
        }
        for (int i = 1, u, v; i < n; i++)
        {
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        dfs(1, 0, 0);
        for (int i = 1; i < n; i++)
        {
            printf("%d ", *s[i].rbegin());
        }
        printf("%d\n",*s[n].rbegin());
    }
    return 0;
}

原文地址:https://www.cnblogs.com/winter-bamboo/p/11381982.html

时间: 2024-10-11 10:16:17

codeforces 842C Ilya And The Tree (01背包+dfs)的相关文章

CF 842C Ilya And The Tree(树上DFS)

题目链接:http://codeforces.com/problemset/problem/842/C 题目: Ilya is very fond of graphs, especially trees. During his last trip to the forest Ilya found a very interesting tree rooted at vertex 1. There is an integer number written on each vertex of the

[Swust OJ 465]--吴奶奶买鱼(0-1背包+dfs)

题目链接:http://acm.swust.edu.cn/problem/465/ Time limit(ms): 1000 Memory limit(kb): 65535 Description 吴奶奶有个可爱的外孙女——琪琪,她很喜欢小动物,尤其喜欢养鱼.为了让小孙女养到漂亮的小鱼,吴奶奶一大早就到花鸟鱼虫市场买鱼.这个市场可真大,里面有各种各样的宠物,就连宠物鱼都有好几十种.这些鱼实在是太美了,买的人越来越多,可是因为货源有限,卖鱼的老板不得不规定:同一种鱼,每个人最多只能买一条,并且有些

hdu3448 01背包+dfs

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3448 Description 0/1 bag problem should sound familiar to everybody. Every earth man knows it well. Here is a mutant: given the capacity of a bag, that is to say, the number of goods the bag can ca

HDU_2079_(01背包)(dfs)

选课时间(题目已修改,注意读题) Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4478    Accepted Submission(s): 3480 Problem Description 又到了选课的时间了,xhd看着选课表发呆,为了想让下一学期好过点,他想知道学n个学分共有多少组合.你来帮帮他吧.(xhd认为一样学分的课没区别)

POJ3628 Bookshelf 2(01背包+dfs)

Bookshelf 2 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8745   Accepted: 3974 Description Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly, and now the only available

Bookshelf 2 poj3628(01背包/DFS)

http://poj.org/problem?id=3628 题意:现有一个书架,N头牛,农场主想把这些牛放在书架上,当然,书架是有固定的高度的.现在问你在这些牛之中,其中一些牛的高度加在一块比书架高的最小差值是多少? 分析: 两种方法:(1)01背包,算得所有牛的高度,然后dp一遍,再找比书架高的最小值,两数相减即可.           (2)DFS,DFS(牛的坐标, 牛高度的总和),若在DFS过程中,牛高度的总和>=书架高度,则可以求我们所需要的值 01背包: #include<std

CodeForces 682C Alyona and the Tree (树上DFS)

题意:给定一棵树,每个叶子有一个权值,每条边也有一个权值,现在让你删最少的结点,使得从任何结点出发到另一个结点的边上权值和都小于两个结点的权值. 析:很明显是DFS,不过要想找出最少的结点可能不太容易,所以我们可以先找出剩下结点最多,那么用总数减去这个就好,那么怎么找哪些结点是剩下的呢?首先要知道,如果一个结点要被删掉, 那么它的子树肯定也要被删掉,并且,要满足dist(v, u) <= a[u]才是可能留下的,那么只要dist(v, u) >a[u],就不要,所以一定要注意的是,结点的距离可

01背包 Codeforces Round #267 (Div. 2) C. George and Job

题目传送门 1 /* 2 题意:选择k个m长的区间,使得总和最大 3 01背包:dp[i][j] 表示在i的位置选或不选[i-m+1, i]这个区间,当它是第j个区间. 4 01背包思想,状态转移方程:dp[i][j] = max (dp[i-1][j], dp[i-m][j-1] + sum[i] - sum[i-m]); 5 在两个for循环,每一次dp[i][j]的值都要更新 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #i

转化一下就是01背包 CodeForces 433A - Kitahara Haruki&#39;s Gift

Kitahara Haruki has bought n apples for Touma Kazusa and Ogiso Setsuna. Now he wants to divide all the apples between the friends. Each apple weights 100 grams or 200 grams. Of course Kitahara Haruki doesn't want to offend any of his friend. Therefor