zoukankan      html  css  js  c++  java
  • P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat…

      一道比较经典的题(蒟蒻的我没有一次切掉)……

      首先这道题要优化的原因就是数据范围,要是O(n2)  “  显然  ” 会超时。。。

      那么我们很不情愿不得已不开心地最终被迫考虑一下优化(说实话好多算法都是为优化而生的啊)。

      首先记录所有点(记得点上有可能有好几头牛)到根节点的路径之和。

      那么每一次考虑,将汇聚的点从父亲改到现在到的这个儿子,那么,以儿子节点作为根的子树上的所有点,就都少走了从儿子到父亲的距离,那么除这些点以外的点,它们都要多走从儿子到父亲的距离。

      那么我们只要一开始随意找一个点作为root,dfs求出距离和,再来一次dfs从下往上不断更新状态就好,每次取最优解就可以了。

      我第一次没A是因为在第二次dfs的时候忘了继续往上dfs(我对自己表示emmm……),第二次是因为没开long long……

      代码如下(请不要学习黑科技):

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    #define maxn 10000005
    #define int long long
    int num[maxn],dis[maxn],head[maxn];
    struct node
    {
        int to,nxt,w;
    } e[maxn];
    int cnt,tot,n,d,ans;
    void add(int a,int b,int c)
    {
        e[++cnt].to=b;
        e[cnt].nxt=head[a];
        head[a]=cnt;
        e[cnt].w=c;
    }
    void dfs(int u,int fa)
    {
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==fa) continue;
            dfs(v,u);
            num[u]+=num[v];
            d+=e[i].w*num[v];
        }
    }
    void dp(int u,int fa)
    {
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==fa) continue;
            dis[v]=dis[u]-num[v]*e[i].w+(tot-num[v])*e[i].w;
            ans=min(ans,dis[v]);
            dp(v,u);
        }
    }
    main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
        {
            int am;
            scanf("%lld",&am);
            num[i]=am;
            tot+=am;
        }
        for(int i=1;i<n;i++)
        {
            int a,b,c; 
            scanf("%lld%lld%lld",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        dfs(1,0);
        dis[1]=d;
        ans=d;
        dp(1,0);
        printf("%lld",ans);
        return 0;
    }

     

  • 相关阅读:
    LINQ大全。
    李开复回复:为什么很多人进不了Google
    判断输入的是否是数字?
    SQL Server 2005安装详解
    学习asp.net比较完整的流程
    .NET常用网站
    软件设计经典书籍推荐
    Linux 下zip包的压缩与解压
    centos的用户、组权限、添加删除用户等操作的详细操作命令
    CentOS5.5 默认基本服务详解
  • 原文地址:https://www.cnblogs.com/popo-black-cat/p/10206416.html
Copyright © 2011-2022 走看看