hdu 1512

思路:用并查集即可,每次合并的时候将小的集合合并到大的集合上去。理论上的平均复杂度是n*lgn*lgn。

#include<map>

#include<queue>

#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#define Maxn 100010

#define LL long long

#define Mod 1000000007

int sz[Maxn],fa[Maxn];

using namespace std;

priority_queue<int> q[Maxn];

void init()

{

    for(int i=0;i<Maxn;i++){

        sz[i]=1;

        fa[i]=i;

    }

}

int find(int x)

{

    if(x!=fa[x])

        fa[x]=find(fa[x]);

    return fa[x];

}

int merg(int a,int b)

{

    int x=find(a);

    int y=find(b);

    if(x==y) return 0;

    int s1,s2;

    s1=q[x].top();

    s2=q[y].top();

    q[x].pop();

    q[y].pop();

    s1/=2;

    s2/=2;

    if(sz[x]>sz[y]){

        q[x].push(s1);

        q[x].push(s2);

        while(!q[y].empty()){

            q[x].push(q[y].top());

            q[y].pop();

        }

        printf("%d\n",q[x].top());

        sz[x]+=sz[y];

        fa[y]=x;

    }else{

        q[y].push(s1);

        q[y].push(s2);

        while(!q[x].empty()){

            q[y].push(q[x].top());

            q[x].pop();

        }

        printf("%d\n",q[y].top());

        sz[y]+=sz[x];

        fa[x]=y;

    }

    return 1;

}

int main()

{

    int n,m,i,j;

    while(scanf("%d",&n)!=EOF){

        init();

        for(i=0;i<Maxn;i++){

            while(!q[i].empty())

                q[i].pop();

        }

        int val;

        for(i=1;i<=n;i++){

            scanf("%d",&val);

            q[i].push(val);

        }

        scanf("%d",&m);

        int a,b;

        for(i=1;i<=m;i++){

            scanf("%d%d",&a,&b);

            if(!merg(a,b))

                printf("-1\n");

        }

    }

    return 0;

}

 

你可能感兴趣的:(HDU)