现在的位置: 首页 > 综合 > 正文

hdu 3899 树形dp 这个题目貌似不难,可是好像托了很久

2014年09月04日 ⁄ 综合 ⁄ 共 1340字 ⁄ 字号 评论关闭

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3899

题意:一棵树,给出每个点的权值和每条边的长度,点j到点i的代价为点j的权值乘以连接i和j的边的长度。求点x使得所有点到点x的代价最小,输出

非常恶心的题目我调试了N久,一直是WA。最后把long long改成了__int64一下就过了,在此鄙视下杭电的编译器

这道题要两次深搜。

1.求出每个节点作为根,他的下面节点到他的花费,以及数量。

2.求出每个节点的兄弟节点到他的花费以及数量。

3.求出每个节点除了他下面的节点的所有节点到他的花费和数量。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
//内存挂
const int maxn=100002;
int n,m,cnt[maxn],tn[maxn];///每个点的人数
__int64 dis[maxn];///最后要求结果
struct node
{
    __int64 dis;
    int v;
}tmp;
vector<node>p[maxn<<1];
void dfs(int u,int fa,__int64 len)
{
    int i,j,v;
    int sum=p[u].size();
    dis[1]+=len*cnt[u];
    tn[u]=cnt[u];
    for(i=0;i<sum;i++)
    {
        int v=p[u][i].v;
        if(v==fa)continue;
        dfs(v,u,len+p[u][i].dis);
        tn[u]+=tn[v];
    }
}
void dfs1(int u,int fa)
{
    int size=p[u].size();
    for(int i=0;i<size;i++)
    {
        int v=p[u][i].v;
        __int64 w=p[u][i].dis;
        if(v==fa) continue;
        dis[v]=dis[u]+(tn[1]-2*tn[v])*w;
         ///对于一条边,求出这条边上面所以边的长度和和下面所有边的长度和,然后就可以进行转移了
        dfs1(v,u);
    }
}
int main()
{
    int u,v,i,j;
    __int64 w;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
        {
          scanf("%d",&cnt[i]);
          dis[i]=0;
          p[i].clear();
        }
        for(i=1;i<n;i++)
        {
            scanf("%d%d %I64d",&u,&v,&w);
            tmp.v=v,tmp.dis=w;
            p[u].push_back(tmp);
            tmp.v=u,tmp.dis=w;
            p[v].push_back(tmp);
        }
        dfs(1,-1,0);
        __int64 ans=dis[1];
        dfs1(1,0);
        for(i=2;i<=n;i++)
        {
            if(ans>dis[i]) ans=dis[i];
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
/*
3
1
1
2
1 2 2
2 3 1
4
100
1
1
1
1 2 1
2 3 1
2 4 1
*/

抱歉!评论已关闭.