hdu 3938 Portal

来源:互联网 发布:知乎 正义联盟 编辑:程序博客网 时间:2024/06/01 10:29

题意在csj小盆友的指导下看懂了 T T 。。。我表示,这个题的题意真的很模糊。。

给你力量L,求有多少条path的力量小于等于L。

这个path消耗的力量是T,T是U到V上最长的边。

所以说,只要求得有多少个点对使得点对之间的最大的边小于L即可。

采用并查集,离线计算,询问从小到大排序,然后边从小到大排序,然后一个一个加入并查集中,加一条,计算一次两个集合的点的数目的乘积即可。

#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define BUG puts("here!!!")using namespace std;const int MAX = 50010;struct NODE{int s,t,len;};struct IND{int ind,q,cnt;};IND id[MAX*2];NODE node[MAX];int num[MAX/5];int pre[MAX/5];int out[MAX];bool cmp(NODE a,NODE b){return a.len < b.len;}int find(int x){while( pre[x] != x )x = pre[x];return x;}int Union(int s,int t){int a = find(s);int b = find(t);int sum = 0;if( a != b )sum = num[a] * num[b];if( a < b ){pre[s] = pre[t] = pre[b] = a;num[a] += num[b];}if( b < a ){pre[s] = pre[t] = pre[a] = b;num[b] += num[a];}return sum;}bool cmp1(IND a,IND b){return a.q < b.q;}int main(){int n,m,q,l;while( ~scanf("%d%d%d",&n,&m,&q) ){memset(id,0,sizeof(id));for(int i=0; i<m; i++)scanf("%d%d%d",&node[i].s,&node[i].t,&node[i].len);sort(node,node+m,cmp);for(int i=0; i<q; i++){scanf("%d",&id[i].q);id[i].ind = i;}sort(id,id+q,cmp1);for(int i=0; i<=n; i++){pre[i] = i;num[i] = 1;}int cnt = 0;for(int i=0; i<q; i++){int ans = id[i-1].cnt;while( cnt < m && node[cnt].len <= id[i].q ){int a = node[cnt].s;int b = node[cnt].t;ans += Union(a,b);cnt++;}out[id[i].ind] = id[i].cnt = ans;}for(int i=0; i<q; i++)printf("%d\n",out[i]);}return 0;}


原创粉丝点击