二次联通门 : 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