BZOJ 2435 道路修建 NOI2011 树形DP

  一看到这道题觉得很水,打了递归树形DP后RE了一组,后来发现必须非递归(BFS)

递归版本84分:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,point[1000003],next[2000003],v[2000003],c[2000003],cnt=0,f[1000003];
bool p[1000003];
long long sum=0;
void insect(int x,int y,int z){next[cnt]=point[x];point[x]=cnt;v[cnt]=y;c[cnt]=z;cnt++;}
void dfs(int x)
{
    int i;
    f[x]=1;
    for (i=point[x];i!=-1;i=next[i])
     if (p[v[i]]==0)
         {
             p[v[i]]=1;
            dfs(v[i]);
            f[x]+=f[v[i]];
            sum+=(1LL*c[i]*abs(2*f[v[i]]-N));
        }
}
int main()
{
    int i,x,y,z;
    memset(point,-1,sizeof(point));
    memset(next,-1,sizeof(next));
    memset(v,0,sizeof(v));
    memset(p,0,sizeof(p));
    memset(c,0,sizeof(c));
    memset(f,0,sizeof(0));
    scanf("%d\n",&N);
    for (i=1;i<N;++i)
    {
        scanf("%d %d %d\n",&x,&y,&z);
        insect(x,y,z); insect(y,x,z);
    }p[1]=1;dfs(1);
    printf("%lld\n",sum);
    return 0;
}

BFS版本AC:

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,point[1000003],next[2000003],v[2000003],c[2000003],cnt=0,f[1000003],s[1000003],fa[1000003];
int table[1000003],num=0,du[1000003];
bool p[1000003];
long long sum=0;
void insect(int x,int y,int z){next[cnt]=point[x];point[x]=cnt;v[cnt]=y;c[cnt]=z;cnt++;}
void dfs(int x)
{
    int now,i,tmp=0;
    queue<int>q;
    for (i=1;i<=N;++i)
    {
        if (du[i]==1)
         q.push(i),f[i]=1;
        f[i]=1;
    }
    while (!q.empty())
    {
        now=q.front(); q.pop(); p[now]=1; tmp=now;
        for (i=point[now];i!=-1;i=next[i])
         if (p[v[i]]==0)
         {
             f[v[i]]+=f[now];
             du[v[i]]--;
             if (du[v[i]]==1)
             q.push(v[i]);
         }
    }
    memset(p,0,sizeof(p));
    p[tmp]=1; q.push(tmp);
    while (!q.empty())
    {
        now=q.front(); q.pop();
        for (i=point[now];i!=-1;i=next[i])
         if (p[v[i]]==0)
         {
             p[v[i]]=1;
             sum+=(1LL*c[i]*abs(2*f[v[i]]-N));
             q.push(v[i]);
         }
    }
    printf("%lld\n",sum);
}
int main()
{
    int i,x,y,z;
    memset(point,-1,sizeof(point));
    memset(next,-1,sizeof(next));
    memset(du,0,sizeof(du));
    memset(v,0,sizeof(v));
    memset(p,0,sizeof(p));
    memset(c,0,sizeof(c));
    memset(f,0,sizeof(0));
    scanf("%d\n",&N);
    for (i=1;i<N;++i)
    {
        scanf("%d %d %d\n",&x,&y,&z); du[x]++; du[y]++;
        insect(x,y,z); insect(y,x,z);
    }dfs(1);
    return 0;
}
时间: 2024-10-16 21:18:52

BZOJ 2435 道路修建 NOI2011 树形DP的相关文章

【BZOJ】2435: [Noi2011]道路修建(树形dp)

http://www.lydsy.com/JudgeOnline/problem.php?id=2435 我怎么感觉那么水.. 坑的是,dfs会爆...好吧..用bfs.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue&

【BZOJ-2435】道路修建 (树形DP?)DFS

2435: [Noi2011]道路修建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3115  Solved: 1002[Submit][Status][Discuss] Description 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他们只愿意修建恰好 n – 1条双向道路. 每条道路的修建都要付出一定的费用, 这个费用等于道路长度乘以道路两端的国家

BZOJ 2878([Noi2012]迷失游乐园-树形DP+环加外向树+期望DP+vector的erase)

2878: [Noi2012]迷失游乐园 Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge Submit: 319  Solved: 223 [Submit][Status] Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m只可能等于n或者n-1).小Z现在所在的大门也正好是

[BZOJ 4033] [HAOI2015] T1 【树形DP】

题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Father[i] 之间的边对答案的贡献(比如这条边对黑点对距离和的贡献就是子树内部的黑点数 * 子树外部的黑点数 * 这条边的权值). 然后DFS来求,枚举 i 的每个儿子 j,现在的 f[i][] 是包含了 [1, j-1] 子树,然后两重循环枚举范围是 [1, j - 1] 的子树总 Size 和

bzoj 3566: [SHOI2014]概率充电器 树形DP

首先普及一个概率公式 P(A+B)=P(A)+P(B)-P(AB) 题意:一些充电元件和导线构成一棵树,充电元件是否能充电有2种情况, 1.它自己有qi%的概率充电 2.与它相邻的元件通过导线给它充电(导线有p%的概率导通) 求最终充了电的元件的期望 题解:首先可以将元件能否充电分成3种情况考虑, 1.它自己给自己充好了电 2.它的儿子方向给它传送了电 3.它的父亲方向给它传送了电. 对于1,题目已经给出可以直接赋值, 对于2,可以通过一次树的深度遍历求得.pson[now]=pson[now]

BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. --------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm&

BZOJ 2314: 士兵的放置( 树形dp )

树形dp... dp(x, 0)表示结点x不放士兵, 由父亲控制: dp(x, 1)表示结点x不放士兵, 由儿子控制: dp(x, 2)表示结点x放士兵. ------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace st

BZOJ 2286 消耗战 (虚树+树形DP)

给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<=500000) 考虑树形DP,我们令mn[i]表示i节点无法与1节点相连切除的最小权值.显然有mn[i]=min(E(fa,i),mn[fa]).大致就是i到1的简单路径上的最小边.我们对于每个询问.把询问的点不妨称为关键点.令dp[i]表示i节点不能与子树的关键点连接切掉的最小权值.那么有,如果son[i]

BZOJ 4726 POI 2017 Sabota? 树形DP

4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved: 49[Submit][Status][Discuss] Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变成叛徒