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;
}

 

posted @ 2017-07-19 19:34  ZlycerQan  阅读(260)  评论(0编辑  收藏  举报