您的位置:首页 > 其它

hdu 3938(离线并查集)

2012-04-14 15:33 197 查看
/*

离线并查集,边按小到大排序,询问也按小到大排序;

对于询问x,答案就是询问x-1的值加上询问x-1的L1和询问x的L2之间的边合并带来的值

对于一条属于L1和L2之间的边,如果端点u,v在一个集合中,忽略,否则新开的路是u

所在集合的大小乘上v所在集合的大小

*/

#include
<cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

struct EDGE

{

int u, v, val;

}edge[50000 + 1234];

struct QUE

{

int id, val;

}l[10000 + 123];

int n, m, q;

int p[10000 + 123];

int num[10000 + 123];

int cou[10000 + 123];

bool cmp(EDGE x, EDGE y)

{

return x.val < y.val;

}

bool cmp2(QUE x, QUE y)

{

return x.val < y.val;

}

void init()

{

for(int i = 1; i <= n; i++)

{

p[i] = i;

num[i] = 1;

}

}

int find(int k)

{

if(k != p[k]) p[k] = find(p[k]);

return p[k];

}

int Union(int a, int b)

{

a = find(a);

b = find(b);

if(a == b) return 0;

int t = num[a] * num[b];

p[b] = a;

num[a] += num[b];

num[b] = 0;

return t;

}

int main()

{

while(scanf("%d%d%d", &n, &m, &q) != EOF)

{

for(int i = 0; i < m; i++) scanf("%d%d%d",&edge[i].u, &edge[i].v, &edge[i].val);

sort(edge, edge + m, cmp);

for(int i = 0; i < q; i++)

{

scanf("%d", &l[i].val);

l[i].id = i;

}

sort(l, l + q, cmp2);



init();

int begin = 0;

int ans = 0;

for(int i = 0; i < q; i++)

{

while(edge[begin].val <= l[i].val && begin < m)

{



ans += Union(edge[begin].u, edge[begin].v);

begin++;

}

cou[l[i].id] = ans;

}



for(int i = 0; i < q; i++)

printf("%d\n", cou[i]);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: