City
题意 :
给出一个图,每次询问给出x ,每次将边权< x 的边摧毁,问还能互相到达的点的对数。
思路 :
将k值和边权排序,从大到小并查集不断加边,计算贡献即可。
AC代码 :
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5 + 5;
pair<PII, int> a[N];
int pre[N], cnt[N];
int W[N], res[N]; //统计城市数
int n, m, q, ans = 0;
PII p;
bool cmp(pair<PII, int> x, pair<PII, int> y)
{
return x.second < y.second;
}
int find(int x)
{
if (pre[x] != x)
pre[x] = find(pre[x]);
return pre[x];
}
void merge(int a, int b)
{
int x = find(a);
int y = find(b);
if (x != y)
{
pre[x] = y;
ans = ans + cnt[x] * cnt[y];
cnt[y] = cnt[x] + cnt[y];
cnt[x] = 0;
}
}
void init()
{
ans = 0;
for (int i = 1; i <= n; i++)
{
pre[i] = i;
cnt[i] = 1;
}
}
signed main()
{
IOS;
int t;
cin >> t;
while (t--)
{
cin >> n >> m >> q;
init();
for (int i = 1; i <= m; i++)
{
int x, y, w;
cin >> x >> y >> w;
p.first = x;
p.second = y;
a[i].first = p;
a[i].second = w;
W[i] = w;
}
sort(a + 1, a + 1 + m, cmp);
for (int i = m; i >= 1; i--)
{
merge(a[i].first.first, a[i].first.second);
res[i] = ans;
}
sort(W + 1, W + 1 + m);
while (q--)
{
int x;
cin >> x;
if (x > a[m].second)
{
cout << 0 << endl;
}
else
{
int temp = lower_bound(W + 1, W + 1 + m, x) - W;
cout << res[temp] << endl;
}
}
}
return 0;
}