题目大意是:
有一些点,每个点都有一个重量值,然后给出了一些边,每个边都有一个权值
最后让用一些边组成一棵树,使得花费最少,每个边(u,v)的花费=(边得所有子孙节点的重量和)*(该边的权值)
对于这个花费,可以看出,对于每条边(u,v),其花费就相当于每个在后面的结点都走了这个边一次,
那么我们可以假想,已经形成了最优的树,观察这颗树,就能发现,对于一条边(u,v),由于边的子女都走了这条边一次,而且是在一棵树中,那么从根结点到边的某个子女结点的路径必然包含(u,v),其他边同理,那么所有边的花费之和,就可以转化为(从根结点到某个结点的路径长度*结点重量)之和 那么之后就是求最短路径了
那么所有点的最短路径一定是一棵树吗? 这个是显然的 ,因为如果形成环了,到达某个点就出现了多个路径,就要删去长的那条,使其没有环
然后这题需要注意的是,某些地方会超过int,所以开成int64就好了,INF的值也设的大一些。比如100亿,因为最短路径的极限数据应该是5W*2^16>2^31
/* ID: sdj22251 PROG: subset LANG: C++ */ #include <iostream> #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cmath> #include <ctime> #define LOCA #define MAXN 50005 #define INF 10000000000LL #define eps 1e-7 using namespace std; struct node { int v; __int64 w; node *next; } edge[MAXN], temp[2 * MAXN]; int n, m, pos; __int64 d[MAXN]; int q[MAXN * 4]; bool visited[MAXN]; __int64 weight[MAXN]; void spfa(int src, __int64 *ecost) //src是起点, ecost是边权 { int h, t, u; node *ptr; h = 0, t = 1; memset(visited, 0, sizeof(visited)); q[0] = src; ecost[src] = 0; visited[src] = true; while(h < t) { u = q[h++]; visited[u] = false; ptr = edge[u].next; while(ptr) { if(ecost[ptr -> v] > ecost[u] + ptr -> w) { ecost[ptr -> v] = ecost[u] + ptr -> w; if(!visited[ptr -> v]) { q[t++] = ptr -> v; visited[ptr -> v] = true; } } ptr = ptr -> next; } } } void insert(const int &x, const int &y, const __int64 &w) { node *ptr = &temp[pos++]; ptr -> v = y; ptr -> w = w; ptr -> next = edge[x].next; edge[x].next = ptr; } void init() { pos = 0; for(int i = 0; i <= n; i++) { edge[i].next = NULL; d[i] = INF; } } int main() { int T, u, v; __int64 w; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); init(); for(int i = 1; i <= n; i++) scanf("%I64d", &weight[i]); for(int i = 0; i < m; i++) { scanf("%d%d%I64d", &u, &v, &w); insert(u, v, w); insert(v, u, w); } spfa(1, d); int flag = 0; __int64 ans = 0; for(int i = 1; i <= n; i++) { if(d[i] == INF) { flag = 1; break; } ans += weight[i] * d[i]; } if(flag) printf("No Answer\n"); else printf("%I64d\n", ans); } return 0; }