HDU 5441 2015年長春icpc網絡賽 並查集

Travel

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 4204    Accepted Submission(s): 1408


Problem Description
Jack likes to travel around the world, but he doesn’t like to wait. Now, he is traveling in the Undirected Kingdom. There aren cities and m bidirectional roads connecting the cities. Jack hates waiting too long on the bus, but he can rest at every city. Jack can only stand staying on the bus for a limited time and will go berserk after that. Assuming you know the time it takes to go from one city to another and that the time Jack can stand staying on a bus is x minutes, how many pairs of city (a,b) are there that Jack can travel from city a to b without going berserk?
 

Input
The first line contains one integer T,T5, which represents the number of test case.

For each test case, the first line consists of three integers n,m and q where n20000,m100000,q5000. 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 d100000. 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.

 

Output
You should print q lines for each test case. Each of them contains one integer as the number of pair of cities(a,b) which Jack may travel from a to b within the time limit x.

Note that (a,b) and (b,a) are counted as different pairs and a and b must be different cities.
 

Sample Input
1 5 5 3 2 3 6334 1 5 15724 3 5 5705 4 3 12382 1 3 21726 6000 10000 13000
 

Sample Output
2 6 12
 

Source


題意:

給出一些點、邊以及邊的權重,有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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章