求小于L的路径点对数(路上的最大值),按权值排序,从小到大并查集建图,有点kruskal的意思。
/** @Date : 2017-09-22 17:30:11
* @FileName: HDU 3938 并查集 离线.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e4+20;
const double eps = 1e-8;
int n, m, q;
struct yuu{
int a, b;
int l;
}e[N*5];
struct sion{
int m, l;
}qu[N];
int cmp1(yuu a, yuu b)
{
return a.l < b.l;
}
int cmp2(sion a, sion b)
{
return a.l < b.l;
}
int fa[N];
LL cnt[N];
LL ans[N];
int find(int x)
{
if(x != fa[x])
fa[x] = find(fa[x]);
return fa[x];
}
int join(int a, int b)
{
int x = find(a);
int y = find(b);
int t = 0;
if(x != y)
{
t = cnt[x] * cnt[y];
fa[y] = x;
cnt[x] += cnt[y];
cnt[y] = 0;
return t;
}
return 0;
}
int main()
{
while(~scanf("%d%d%d", &n, &m, &q))
{
MMF(ans);
MMF(cnt);
for(int i = 0; i <= n; i++)
fa[i] = i, cnt[i] = 1;
for(int i = 0; i < m; i++)
scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].l);
for(int i = 0; i < q; i++)
scanf("%d", &qu[i].l), qu[i].m = i;
sort(e, e + m, cmp1);
sort(qu, qu + q, cmp2);
int j = 0;
LL t = 0;
for(int i = 0; i < q; i++)
{
while(j < m && e[j].l <= qu[i].l)
t += join(e[j].a, e[j].b), j++;
ans[qu[i].m] = t;
}
//cout << "~";
for(int i = 0; i < q; i++)
printf("%lld\n", ans[i]);
}
return 0;
}
原文:http://www.cnblogs.com/Yumesenya/p/7583275.html