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;
}
时间: 2024-10-05 13:22:29

cogs 944. [東方S3] 藤原妹红的相关文章

cogs 942. [東方S3] 比那名居天子

二次联通门 : cogs 942. [東方S3] 比那名居天子 /* cogs 942. [東方S3] 比那名居天子 二分水题 二分所求区间长度 判断后缩小范围即可 */ #include <cstring> #include <cstdio> #define Max 1000000 void read (int &now) { now = 0; register char word = getchar (); while (word < '0' || word &g

cogs 2569. [東方] 博丽灵梦 梦想妙珠

二次联通门 : cogs 2569. [東方] 博丽灵梦 梦想妙珠 /* cogs 2569. [東方] 博丽灵梦 梦想妙珠 莫队水过.. 好久没一遍AC了.. 卡线上榜2333 */ #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> char Buf[100000001], *buf = Buf; int BUF = 100000001; void rea

997. [東方S2] 射命丸文

997. [東方S2] 射命丸文 二维前缀和 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 2333 4 int n,m,r,c; 5 int num[maxn][maxn],f[maxn][maxn],ans; 6 char ch; 7 inline void read(int &now) 8 { 9 ch=getchar(); int f=1; now=0; 10 while(ch>'9'||c

明天补完

/* cogs 943. [東方S3] 铃仙?优昙华院?稻叶 概率dp 貌似做麻烦了 邻接矩阵和链式前向星都用上了... f[pos][i][j]表示 第i秒 在i点 上一个经过的点是j 方程: f[pos][i][j]=Σf[pos-1][j][k]*(__out[j]+1-(map[j][k]==1))+f[pos-1][i][j]*(__out[i]+1-(map[i][j]==1) 前面的求和考虑的是上一秒从其他的一个节点走过来 后面的考虑的是上一秒选择停留在原地 复杂度O(T * N^

对于有关东方的题目的整理。。

东方赛高 此为总贴 收录以东方project为背景的题目. 1. luogu P3345 [ZJOI2015]幻想乡战略游戏 动态点分治(暴力水过) 2. luogu P3344 [ZJOI2015]幻想乡WIFI搭建计划 3. luogu P3343 [ZJOI2015]地震后的幻想乡 4. luogu P3346 [ZJOI2015]诸神眷顾的幻想乡 5. luogu P3347 [ZJOI2015]醉熏熏的幻想乡 6. luogu P1726 上白泽慧音 求强连通分量, 输出最大强连通分量

繁體字顯示問題

宋體筆畫設計簡單,加之hint的作用,所以實用性很高.MingLiU筆畫很有藝術性,hint不好做,所以必須用大字號才能看清楚其細節.因為電腦顯示技術的限制,導致其在普通字體大小下,筆畫基本上是貼在一起,非常不實用.日文有很多字體,主流是哪種我也不知道,不過總體的觀感就是既美觀又實用.簡體字設置成宋體13px,已經基本上能看清楚,正文是16px,效果更好,可以打80分.繁體字設置微軟正黑體,或者宋體,在16px就差強人意了.繁體字設置成MingLiU,如果要求筆畫不發虛,拐角能看清楚,則最少需要

java 翻盖hashCode()深入探讨 代码示例

package org.rui.collection2.hashcode; /** * 覆盖hashcode * 设计HashCode时最重要的因素 就是:无论何时,对同一个对象调用HashCode都应该产生同样的值, * 如果你的HashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化 时 * HashCode就会生成一个不同的散列码,相当于产生一个不同的健 * 此外 也不应该使HashCode依赖于具有唯一性的对象信息,尤其是使用this的值,这只能很糟糕, * 因为这

那些年我們未實現的夢

昨天晚飯之後和大學同學在西門町紅樓後面的酒吧聊了很多,聊了過去,現在,當然也不斷地在弄清我們的未來. “清華北大” 這是我的第一個夢想吧,可能大多數中國的學生的夢想,但是能去的人才有幾個呢.特別是在小城市,每年也就三四個考上清華和北大的.大我兩歲的表哥還是我們市歷史上第一個報送到清華的學生,而下一個這麼多年過去也一直沒有.我不算是很努力的學生,但是覺得自己有點小聰明,也沒有像別人題海戰術,基本上就是把老師上課的內容搞明白,時常溫故而知新.從高一開始的年級400多名,經過一年努力,逐步穩定在二十名

元朝皇帝列表 元朝历代皇帝简介

元朝皇帝列表 元朝历代皇帝简介 元朝(公元1206年-1368年),始于太祖铁木真,终于元顺帝,共15帝.元朝是蒙古族的王朝,疆域宽广,但统治残暴,致使王朝短命. 元朝皇帝列表: 太祖铁木真(1162-1227)1206年称汗,在位22年 太祖铁木真,姓奇渥温,名铁木真,蒙古族人.1206年,被蒙古贵族推举为“成吉思汗”.之后进行大规模的侵略扩张,死于1227年,庙号太祖. 太宗窝阔台(1186-1241)1229年即位,在位13年 窝阔台,成吉思汗的第三子,成吉思汗死后,由其四子拖雷监国一年,