Travel
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 4204 Accepted Submission(s): 1408
For each test case, the first line consists of three integers n,m and q where n≤20000,m≤100000,q≤5000. The Undirected Kingdom has n cities and m bidirectional roads, and there are q queries.
Each of the following m lines consists of three integers a,b and d where a,b∈{1,...,n} and d≤100000. It takes Jack d minutes to travel from city a to city b and vice versa.
Then q lines follow. Each of them is a query consisting of an integer x where x is the time limit before Jack goes berserk.
Note that (a,b) and (b,a) are counted as different pairs and a and b must be different cities.
題意:
給出一些點、邊以及邊的權重,有q 次詢問,問你:任意連通的兩點間所有邊的權重都小於 x ,這樣的點有多少對
題解:
離線處理
把所有信息保存下來,對於邊,權值按照從小到大排序,詢問的 x 也按照從小到大排序
此時遍歷每一條邊,當小於 x 的時候,我們就加入並查集,計算並查集裏面點對的增量
對於每一棵並查集樹:
若有 n 個點,那麼有 n*(n-1) 種點對
對於兩棵需要合併的樹,它們分別有 a 、 b 個點
那麼需要先得到點對的增量是 (a+b)*(a+b-1) - a*(a-1) -b*(b-1) ,化簡得到 2*a*b
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100007
#define LL long long
struct edge{
int from,to,cost;
bool operator < (const edge& x) const {
return cost < x.cost;
}
}e[maxn];
int a[maxn],ta[maxn],fa[maxn],sum[maxn],ans[maxn];
int find_it(int x){
int tempx=x,t;
while(tempx!=fa[tempx]) tempx=fa[tempx];
while(x!=fa[x]) t=fa[x],fa[x]=tempx,x=t;
return tempx;
}
int unite(int num1,int num2){
int tx=find_it(num1);
int ty=find_it(num2),t=0;
if(tx!=ty){
fa[tx]=ty;
t=2*sum[tx]*sum[ty];
sum[ty]+=sum[tx];
}
return t;
}
int main()
{
int T;
int n,m,q;
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&q);
for(int i=0;i<m;i++)
scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].cost);
sort(e,e+m);
for(int i=0;i<q;i++)
scanf("%d",&a[i]),ta[i]=a[i];
sort(a,a+q);
memset(ans,0,sizeof(ans));
for(int i=0;i<=n;i++) fa[i]=i,sum[i]=1;
int pos=0,t=0;
for(int i=0;i<m;i++){
while(pos<q&&e[i].cost>a[pos]) ans[a[pos++]]=t;
if(pos<q) t+=unite(e[i].from,e[i].to);
}
while(pos<q) ans[a[pos++]]=t;
for(int i=0;i<q;i++)
printf("%d\n",ans[ta[i]]);
}
return 0;
}