当然题目上不是这么写的。它问的是有多少种路径,这里就比较模糊了,到底两个路径怎样才算是两种路径呢,这时候重新看题,可以发现,如果理解为路径中经过的点不同的话,题目中给的所谓两点间的花费这个定义就没有意义了,所以就可以猜测,题目要求的是有多少个点对了。
然后就明确题意后,再进行分析。对一个点对的所有路径,只要最短最大边的那条路径出现,其后的所有较大最大边的路径都是毫无意义的,那么不妨将所有的边按照权值从小对大进行排序,用并查集的方法,进行加边,已经连通的点就不再管。那么每次加边的时候,是将两个集合并在一起的过程,假设集合大小分为a,b,显然路径的种类是a*b个,此时对于所有大于集合中最大边的L,都要加上这个种类数了。
那么,算法就明确了,为离线算法,先输入所有的边和L,对所有的L进行排序,对所有的边进行排序,都为从小到大,然后对每个L,将比其小的边权的边都并在一起,计算种类数即可。
/* ID: CUGB-wwj PROG: 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 INF 2000000000 #define MAXN 10005 #define L(x) x<<1 #define R(x) x<<1|1 using namespace std; int n, m, q; int father[MAXN], num[MAXN]; long long out[MAXN]; struct node { int u, v, w; bool operator <(const node &a)const { return w < a.w; } }edge[MAXN * 10]; struct wen { int l, id; bool operator <(const wen &a)const { return l < a.l; } }p[MAXN]; void init() { for(int i = 1; i <= n; i++) { father[i] = i; num[i] = 1; } } int find(int x) { if(father[x] == x) return x; int t = find(father[x]); father[x] = t; return t; } int join(int x, int y) { int fx = find(x); int fy = find(y); if(fx == fy) return 0; int t = num[fx] * num[fy]; num[fx] += num[fy]; num[fy] = 0; father[fy] = fx; return t; } int main() { while(scanf("%d%d%d", &n, &m, &q) != EOF) { init(); for(int i = 1; i <= m; i++) scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); sort(edge + 1, edge + m + 1); for(int i = 1; i <= q; i++) { scanf("%d", &p[i].l); p[i].id = i; } sort(p + 1, p + q + 1); int pos = 1; long long ans = 0; for(int i = 1; i <= q; i++) { while(pos <= m && edge[pos].w <= p[i].l) { ans += join(edge[pos].u, edge[pos].v); pos ++; } out[p[i].id] = ans; } for(int i = 1; i <= q; i++) printf("%I64d\n", out[i]); } return 0; }