Hdu 3938 Portal【離線+並查集+思維】
阿新 • • 發佈:2019-02-07
Portal
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1792 Accepted Submission(s): 883
Problem Description 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
題目大意:
給出N個點,M條無向邊,以及Q個查詢,每個查詢詢問兩點間所有路徑上的最大值最小值為w,並且w<=Qi的點對數。
思路:
①我們首先思考,詢問兩點間所有路徑的最大值最小,其實就是在詢問,從點u到點v最短路徑上的最大值。那麼希望兩點間最短路徑最短,其實問題就相當於求一顆MST。
對應兩點間最短路的最大值,就是聯通點u和點v的最後一條邊的權值。
②那麼我們離線處理問題,將詢問按照從小到大排序,然後將每條邊按照權值從小到大排序,對於當前加入樹邊(u,v,w),對應ans【w】=sum【u】*sum【v】,這裡sum【u】表示的就是點u所在聯通塊點的個數。
③注意資料範圍,過程維護一下即可。
Ac程式碼:
#include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; int f[1050000]; int sum[1050000]; long long int output[1050000]; struct node { int x,y,w; }a[1050000]; struct node2 { int val,pos; }q[1050000]; int cmp(node a,node b) { return a.w<b.w; } int cmp2(node2 a,node2 b) { return a.val<b.val; } int find(int a) { int r=a; while(f[r]!=r) r=f[r]; int i=a; int j; while(i!=r) { j=f[i]; f[i]=r; i=j; } return r; } void merge(int a,int b) { int A,B; A=find(a); B=find(b); if(A!=B) { f[B]=A; sum[A]+=sum[B]; } } int main() { int n,m,qq; while(~scanf("%d%d%d",&n,&m,&qq)) { for(int i=1;i<=n;i++)f[i]=i,sum[i]=1; for(int i=1;i<=m;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w); } for(int i=1;i<=qq;i++) { scanf("%d",&q[i].val);q[i].pos=i; } sort(a+1,a+1+m,cmp); sort(q+1,q+1+qq,cmp2); long long int ans=0; int j=1; for(int i=1;i<=m;i++) { if(find(a[i].x)!=find(a[i].y)) { while(j<=qq&&q[j].val<a[i].w)output[q[j].pos]=ans,j++; ans+=(long long int )sum[find(a[i].x)]*sum[find(a[i].y)]; merge(a[i].x,a[i].y); } } while(j<=qq)output[q[j].pos]=ans,j++; for(int i=1;i<=qq;i++) { printf("%lld\n",output[i]); } } }