• cogs 944. [東方S3] 藤原妹红


    二次联通门 : cogs 944. [東方S3] 藤原妹红

    /*
        cogs 944. [東方S3] 藤原妹红
    
        最小生成树 + 树形dp
        
        首先对原图跑最下生成树
        
        后建出一棵树
        在树上进行dp
        先走到叶子节点, 顺便处理出距离 
        
        最终回溯时更新答案 
    */
    #include <algorithm>
    #include <cstdio>
    
    #define INF 1e30
    
    void read (int &now)
    {
        register char word = getchar ();
        for (now = 0; word < '0' || word > '9'; word = getchar ());
        for (; word >= '0' && word <= '9'; now = now * 10 + word - '0', word = getchar ());
    }
    
    #define Max 300010
                 
    int N, M;
    #define Online
    
    struct Edge_Data
    {
        int from;
        int to;
        double value;
        
        bool operator < (const Edge_Data &now) const
        {
            return this->value < now.value;
        }
    };
    
    double Max_dis = INF;
    int Answer;
    
    class Tree_Dp_Type
    {
        private :
            
            int __to[Max], count[Max];
            double __value[Max];
            int __next[Max];
            
            int edge_list[Max];
            int Edge_Count;
            
            double dis[Max];
            double Sum;
            
        public :
            
            Tree_Dp_Type ()
            {
                Sum = 0;
            }
            
            inline void Insert_edge (int from, int to, double value)
            {
                Edge_Count ++;
                __to[Edge_Count] = to;
                __next[Edge_Count] = edge_list[from];
                edge_list[from] = Edge_Count;
                
                Edge_Count ++;
                __to[Edge_Count] = from;
                __value[Edge_Count] = __value[Edge_Count - 1] = value;
                __next[Edge_Count] = edge_list[to];
                edge_list[to] = Edge_Count;
                
                count[from] ++;
                count[to] ++;
                Sum += value;
            }
            
            double Dfs (int now, int father)
            {
                double avg = Sum / (double) count[now];
                double res = 0, __res = 0;
    
                for (int i = edge_list[now]; i; i = __next[i])        
                {
                    
                    if (__to[i] == father)
                         continue;
                         
                    dis[__to[i]] = __value[i] + Dfs (__to[i], now);
                    res += (dis[__to[i]] - avg) * (dis[__to[i]] - avg);
                    __res += dis[__to[i]];
                }
                res += (Sum - __res - avg) * (Sum - __res - avg);
                
                if (count[now] != 1 && (res < Max_dis || (res == Max_dis && Answer > now))) 
                {
                    Answer = now;
                    Max_dis = res;
                }
                
                return __res;
            }
    };
    
    Tree_Dp_Type Dp;
    
    class Min_Out_Tree_Type
    {
        
        private :
            
            int father[Max];
            
            int edge_list[Max];
            int Edge_Count;
            
            Edge_Data edge[Max * 8];
            
        public :
            
            void Prepare (int Limit)
            {/*
                register int i;
                for (i = 1; i <= Limit; i += 3)
                {
                    father[i] = i;
                    father[i + 1] = i + 1;
                    father[i + 2] = i + 2;
                }
                if (i > Limit)
                    for (i -= 3; i > N; i ++)
                        father[i] = i;
            */
                for (register int i = 1; i <= Limit; i ++)
                    father[i] = i;
            }
            
            int Find (int x)
            {
                return father[x] == x ? x : father[x] = this->Find (father[x]);
            }
            
            inline void Insert_edge (int from, int to, double key)
            {
                Edge_Count ++;
                edge[Edge_Count].from = from;
                edge[Edge_Count].to = to;
                edge[Edge_Count].value = key;
            }
            
            void Get_Min_Value_Tree ()
            {
                std :: sort (edge + 1, edge + M + 1);
                
                int Count = 0;
                for (register int i = 1, x, y; i <= M; i ++)
                {
                    x = this->Find (edge[i].from);
                    y = this->Find (edge[i].to);
                    
                    if (x != y)
                    {
                        father[x] = y;
                        Count ++;
                        Dp.Insert_edge (edge[i].from, edge[i].to, edge[i].value);
                    }
                    if (Count == N - 1)
                        break;
                }
            }
    };
    
    Min_Out_Tree_Type Get_Tree;
    
    int main (int argc, char *argv[])
    {
    
    #ifdef Online
        
        freopen ("mokou.in", "r", stdin);
        freopen ("mokou.out", "w", stdout);
        
    #endif
        
        read (N);
        read (M);
        
        int x, y;
        double z;
        Get_Tree.Prepare (N);
        
        for (int i = 1; i <= M; i ++)
        {
            read (x);
            read (y);
            scanf ("%lf", &z);
            Get_Tree.Insert_edge (x, y, z); 
        }
        
        Get_Tree.Get_Min_Value_Tree ();
        
        Dp.Dfs (1, 0);
        
        printf ("%d", Answer);
        
        return 0;
    }
  • 相关阅读:
    WPF获取分辨率2
    怎样将UNIX Shell作为Concurrent Program来运行
    转 FRM40654 Record has been updated Requery block to see change
    各模组相关interface
    EBS 表后缀的含义
    Oracle Form開發Form消息提示
    EBS多组织(OU
    EBS 开发基础知识
    FORM:在不同窗口中传递参数
    AR 金额计算
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7207513.html
Copyright © 2020-2023  润新知