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;
}
posted @ 2017-09-23 22:46  Lweleth  阅读(272)  评论(0编辑  收藏  举报