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 mbidirectional 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 band 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.
Note that (a,b) and (b,a) are counted as different pairs and a and b must be different cities.
solution:
有一個n個點的無向圖,給出m條邊的邊權,給出q次詢問,每次給出一個值,求用到所有邊權不大於這個值的邊的情況下,能夠互相到達的點對的個數。剛開始以爲是最短路變形,但後來發現可以用帶權並查集做,把查詢讀入後從小到大排序,然後對於每次查詢,我用並查集維護邊權不大於這個值的每個聯通塊中節點個數,若可以合併u,v,且num[i]代表以i爲根的聯通塊的節點數,則要加上(num[u] + num[v])*(num[u] + num[v] - 1) - num[u] * (num[u] - 1) - num[v] * (num[v] - 1),因爲在次之前我們已經累加過num[i] * (num[i] - 1)。在每次合併時,我們應該選準壓縮路徑的方向,我每次都是把節點編號大的插在節點編號小的下面。
詳細看代碼~
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 20500;
int fa[maxn], num[maxn],ans[maxn];
int n;
struct edge{
int u, v, w;
bool operator <(const edge &x)const
{
return w < x.w;
}
}e[maxn*5];
struct Query
{
int id, x;
bool operator <(const Query &a)const
{
return x < a.x;
}
}query[maxn];
void init()
{
for (int i = 1; i <= n; i++)
{
num[i] = 1;
fa[i] = i;
}
}
int find(int x)
{
if (fa[x] == x)return x;
return fa[x] = find(fa[x]);
}
void _union(int x, int y)
{
x = find(x); y = find(y);
if (x > y)swap(x, y);
fa[y] = x;
num[x] += num[y];
}
int main()
{
int t,m,q;
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &n, &m, &q);
init();
for (int i = 0; i <m; i++)
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
sort(e, e + m);
for (int i = 0; i < q; i++)
{
query[i].id = i;
scanf("%d", &query[i].x);
}
sort(query, query + q);
int j = 0, tmp = 0;
for (int i = 0; i < q; i++)
{
while (j < m&&e[j].w <= query[i].x)
{
int u = find(e[j].u), v = find(e[j].v);
j++;
if (u == v)continue;
tmp += (num[u] + num[v])*(num[u] + num[v] - 1) - num[u] * (num[u] - 1) - num[v] * (num[v] - 1);
_union(u, v);
}
ans[query[i].id] = tmp;
}
for (int i = 0; i < q; i++)
printf("%d\n", ans[i]);
}
return 0;
}