1. 程式人生 > >cogs 944. [東方S3] 藤原妹紅

cogs 944. [東方S3] 藤原妹紅

scan tin 二次 data bsp class lis 上進 argv

二次聯通門 : 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; }

cogs 944. [東方S3] 藤原妹紅