/* * 解法: 首先是建图, 如果边的权值改为它连接的两个节点的时间 + 它表示的路的时间的两倍, * 那么图的最小生成树就是题解. * 然后就是如何求最小生成树. 这题和其它最小生成树题目不同, 如果用普通的MST算法, * prim或者kruskal, 要进行10000次MST, 显然会超时. 这里要对kruskal算法进行改进. * 如果在加入一条新边之前有一条边不是最小生成树的边, 那么可以证明, 加入了新边, * 那条边依然不会是最小生成树的边. 所以在每一次kruskal的时候, 把不是最小生成树 * 的边从边集里面剔除, 那么每次MST边都不会超过N条, 这样的话时间复杂度为O(M * N). * 再加上点优化就能很轻松地在规定时间内过了. * 注意: 很阴险的一点是年是分为平年和闰年的...如果天数恰好在[365, 366)... */ #include <cstdio> #include <list> #include <algorithm> using namespace std; const int MAXN = 205; const int MAXM = 10005; const int HOURS_PER_DAY = 24; const int DAYS_PER_YEAR = 365; const int DAYS_PER_LEAP_YEAR = 366; struct Edge { int x, y, t; bool operator < (const Edge &oth) { return t < oth.t; } }; struct DisjoinSet { int pare[MAXN]; void init(int n) { for (int i = 0; i < n; i++) pare[i] = i; } int find(int x) { if (pare[x] != x) pare[x] = find(pare[x]); return pare[x]; } bool set(int x, int y) { x = find(x); y = find(y); if (x == y) return false; pare[y] = x; return true; } } ds; bool IsLeapYear(int year) { return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; } int T[MAXN]; list<Edge> E; list<Edge>::iterator it; int main() { int N, M, i, t, cost; bool run; Edge ne; while (scanf("%d %d", &N, &M) != EOF) { for (i = 0; i < N; i++) { scanf("%d", T + i); T[i] = T[i] * HOURS_PER_DAY; } ds.init(N); E.clear(); t = N - 1; cost = DAYS_PER_LEAP_YEAR * HOURS_PER_DAY + 1; run = false; for (i = 0; i < M; i++) { scanf("%d %d %d", &ne.x, &ne.y, &ne.t); ne.t = ne.t + ne.t + T[ne.x] + T[ne.y]; if (t > 0) { E.push_back(ne); if (ds.set(ne.x, ne.y)) { t--; if (t <= 0) { run = true; E.sort(); } } } else if (ne.t < E.back().t) { for (it = E.begin(); (*it) < ne; it++) {} E.insert(it, ne); run = true; } if (run) { cost = 0; ds.init(N); for (it = E.begin(); it != E.end(); ) { if (ds.set((*it).x, (*it).y)) { cost = cost + (*it).t; it++; } else it = E.erase(it); } run = false; } if (cost <= HOURS_PER_DAY * (IsLeapYear(1000 + i) ? DAYS_PER_LEAP_YEAR : DAYS_PER_YEAR)) printf("%.2lf/n", 1.0 * cost / HOURS_PER_DAY); else printf("-1/n"); } printf("/n"); } return 0; }