题目
Jack likes to travel around the world, but he doesn’t like to wait. Now, he is traveling in the Undirected Kingdom. There are n cities and m bidirectional roads connecting the cities. Jack hates waiting too long on the bus, but he can rest at every city. Jack can only stand staying on the bus for a limited time and will go berserk after that. Assuming you know the time it takes to go from one city to another and that the time Jack can stand staying on a bus is x minutes, how many pairs of city (a,b) are there that Jack can travel from city a to b without going berserk?
Input
The first line contains one integer T,T≤5, which represents the number of test case.
For each test case, the first line consists of three integers n,m and q where n≤20000,m≤100000,q≤5000. The Undirected Kingdom has n cities and m bidirectional roads, and there are q queries.
Each of the following m lines consists of three integers a,b and d where a,b∈{1,…,n} and d≤100000. It takes Jack d minutes to travel from city a to city b and vice versa.
Then q lines follow. Each of them is a query consisting of an integer x where x is the time limit before Jack goes berserk.
Output
You should print q lines for each test case. Each of them contains one integer as the number of pair of cities (a,b) which Jack may travel from a to b within the time limit x.
Note that (a,b) and (b,a) are counted as different pairs and a and b must be different cities.
Sample Input
1
5 5 3
2 3 6334
1 5 15724
3 5 5705
4 3 12382
1 3 21726
6000
10000
13000
Sample Output
2
6
12
思路
最开始的想法是找到合适的边,构建一棵或若干树,找其中任意两点就是C(n, 2)(n是一棵树所有节点数),用并查集和map就可以实现,结果超时了。
然后想到先打表再查询的方法,先对所有路按时间从小到大sort一下,然后从前往后向集合中加边,会出现两个集合合并的情况,变化量是C(x+y, 2) - C(x,2)-C(y,2)。
代码
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mem(a,n) memset(a,n,sizeof(a))
#define FRER() freopen("input.txt", "r", stdin)
#define FREW() freopen("output.txt", "r", stdin)
typedef long long LL;
using namespace std;
const int inf = 0x3f3f3f3f, maxn = 100000 + 10;
struct sc{
int u,v;
int t;
} r[maxn];
bool cmp(const sc & a, const sc & b)
{
return a.t<b.t;
}
LL ans[maxn];
LL cnt[maxn];
int pre[maxn];
int Find(int x)
{
return x==pre[x]?x:pre[x]=Find(pre[x]);
}
void init(int n, int m)
{
mem(ans,0);
for(int i=1;i<=n;i++){
cnt[i]=1;
pre[i]=i;
}
int temp=0;
for(int i=0;i<m;i++){
int fx=Find(r[i].u);
int fy=Find(r[i].v);
if(fx!=fy){
pre[fx]=fy;
temp=ans[r[i].t] = temp + (cnt[fx]+cnt[fy]-1)*(cnt[fx]+cnt[fy]) - (cnt[fx]-1)*cnt[fx]-(cnt[fy]-1)*cnt[fy];
cnt[fy]=cnt[fy]+cnt[fx];
}
}
for(int i=1;i<=maxn;i++){
if(!ans[i]) ans[i]=ans[i-1];
}
}
int main()
{
//FRER();
int T; cin >> T;
int n, m, q;
while(T--){
scanf("%d%d%d", &n, &m, &q);
for(int i=0; i < m; i++) {
scanf("%d%d%d", &r[i].u, &r[i].v, &r[i].t);
}
sort(r,r+m,cmp);
init(n,m);
int query;
while(q--) {
scanf("%d", &query);
printf("%lld\n", ans[query]);
}
}
return 0;
}