1. 程式人生 > >3938(Portal)並查集+離線

3938(Portal)並查集+離線

ZLGG found a magic theory that the bigger banana the bigger banana peel .This important theory can help him make a portal in our universal. Unfortunately, making a pair of portals will cost min{T} energies. T in a path between point V and point U is the length of the longest edge in the path. There may be lots of paths between two points. Now ZLGG owned L energies and he want to know how many kind of path he could make.

Input

There are multiple test cases. The first line of input contains three integer N, M and Q (1 < N ≤ 10,000, 0 < M ≤ 50,000, 0 < Q ≤ 10,000). N is the number of points, M is the number of edges and Q is the number of queries. Each of the next M lines contains three integers a, b, and c (1 ≤ a, b ≤ N, 0 ≤ c ≤ 10^8) describing an edge connecting the point a and b with cost c. Each of the following Q lines contain a single integer L (0 ≤ L ≤ 10^8).

Output

Output the answer to each query on a separate line.

Sample Input

10 10 10
7 2 1
6 8 3
4 5 8
5 8 2
2 8 9
6 4 5
2 1 5
8 10 5
7 3 7
7 8 8
10
6
1
5
9
1
8
2
7
6

Sample Output

36
13
1
13
36
1
36
2
16
13

先說題目意思吧 真TM想踹題白白浪費一小時就搜各個部落格就為了想知道題目是啥意思 好吧 它真的是一道好題

給出n,m,q; n是有多少個點  m是有多少遍 q是有多少詢問

在給出當前的能量的情況下!

就是求A集合  和 B集合之間 他們之間相互連線!相互連線起來可以有多少個點對(X,Y)是小於當前的能量

先把邊從小到大排個序,怎麼那麼像最小生成樹。。。。。啊啊啊啊 其實就是就有點像變形最小生成樹

離線離線就是輸入完在處理,咋們平時不都是邊輸入邊merge嗎因為沒有權值啊 這題有啊

舉個栗子

排完序對吧 1 1 2 5 6 6 7 8 9 10

排完序

7 2 1
5 8 2
6 8 3
6 4 5
2 1 5
8 10 5
7 3 7
4 5 8
7 8 8
2 8 9

因為m條邊啊所以肯定不能大於它呢 他們連線花費的東西當然也不能大於當前的能量啊

看下這個地方

當前值為1 時候                      2和7一堆了   此刻點對有1

當前值為1 。。。。。。。沒改變

當前值為2  又增加了一個點對了  58  此刻點對有2  扎堆的有 (27)    (58)

當前值為5!!

6  8== 3對吧 可是此刻 5和8在一起了  6再進去就是加2 對吧  所以 現在加2  點對為  1 + 1 + 2 =4

現在一堆的有 27                         856

6 4 ==5 進去了    所以!此刻 4 和568扎堆了 那麼點對再加3    點對為1+1+2+3=7

現在一堆的有 27                         4856

2 1 ==== 5 進去了 所以!1和27扎堆了  那麼點對再加2   點對為1 + 1 + 2 + 3 + 2 = 9

現在一堆的有 127                         4856

8 10 ====5 進去了 所以! 10 和4856扎堆了 那麼點對為1 + 1 + 2 + 3 + 2 + 4 = 13

現在你懂什麼意思了把?  別管這句話真的

T in a path between point V and point U is the length of the longest edge in the path 害老子想了一晚上生氣

a 集合和b集合聯合在一起 sum = rank[a] * rank[b]   你想想 27   34   他們點對是不是 1 + 1 + 4  對吧  rank[a] = 2;

rank[b] = 2;   是吧?  所以就是4 over! 再見!

程式碼!

#include<cstdio>
#include<algorithm>
using namespace std;
int n, m, q;
const int maxn = 1e4+10;
int pre[maxn],ranks[maxn]; 
struct node
{
	int x , y , val; 
	bool operator < (const node &a)const{
     	return val < a.val;
	}
}edge[maxn * 5];
struct GG
{
	int id,q,ans;
}query[maxn];
bool cmp1(GG a, GG b){
	return a.q < b.q;
}
bool cmp2(GG a, GG b){
	return a.id < b.id;
}
int find(int x)
{
	if(pre[x] == x)
		return x;
	else
		return pre[x] = find(pre[x]);	
}
int merge(int x,int y)
{
	int fx = find(x);
	int fy = find(y);
	if(fx != fy)
	{
		pre[fy] = fx;
		int temp = ranks[fx];
		ranks[fx] = ranks[fx] + ranks[fy];
		return temp * ranks[fy];
	}
	return 0;	
} 
int main()
{
	while(~scanf("%d %d %d",&n,&m,&q))
	{
		for(int i = 1 ; i <= m; i++)
			scanf("%d %d %d",&edge[i].x, &edge[i].y, &edge[i].val);
		for(int i = 1; i <= q; i++)
		{
			scanf("%d",&query[i].q);
			query[i].id = i;
			query[i].ans = 0;
		}	
		sort(edge + 1, edge + 1 + m);
		sort(query + 1,query + 1 + q, cmp1);	
		for(int i = 1; i <= m; i ++)
			printf("%d %d %d \n",edge[i].x ,edge[i].y, edge[i].val);
		for(int i = 1; i <= n; i++)
		{
			pre[i] = i;
			ranks[i] = 1;
		}
		int cnt = 1;
		for(int i = 1; i <= q; i ++)
		{
			query[i].ans += query[i - 1].ans;
			while(cnt <= m && edge[cnt].val <= query[i].q) //因為m條邊啊所以肯定不能大於它呢 他們連線花費的東西當然也不能大於當前的能量啊
			{
				query[i].ans += merge(edge[cnt].x, edge[cnt].y);
				cnt++;
			} 
		}
		sort(query + 1,query + 1 + q, cmp2);
		for(int i = 1; i <= q; i ++)
			printf("%d\n",query[i].ans);
	}
	return 0;
}