HDU 3938 并查集
求小于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; }