首页 > 代码库 > hdu3938 Portal 离线的并查集

hdu3938 Portal 离线的并查集

  离线算法是将全部输入都读入,计算出所有的答案以后再输出的方法。主要是为避免重复计算。类似于计算斐波那契数列的时候用打表的方法。

  题目:给一个无向图,求有多少个点对,使得两点间的路径上的花费小于L,这里路径上的花费是这样规定的,a、b两点之间所有的路径中的最大边的最小值。   
  当然题目上不是这么写的。它问的是有多少种路径,这里就比较模糊了,到底两个路径怎样才算是两种路径呢,这时候重新看题,可以发现,如果理解为路径中经过的点不同的话,题目中给的所谓两点间的花费这个定义就没有意义了,所以就可以猜测,题目要求的是有多少个点对了。
然后就明确题意后,再进行分析。对一个点对的所有路径,只要最短最大边的那条路径出现,其后的所有较大最大边的路径都是毫无意义的,那么不妨将所有的边按照权值从小对大进行排序,用并查集的方法,进行加边,已经连通的点就不再管。那么每次加边的时候,是将两个集合并在一起的过程,假设集合大小分为a,b,显然路径的种类是a*b个,此时对于所有大于集合中最大边的L,都要加上这个种类数了。

  那么,算法就明确了,为离线算法,先输入所有的边和L,对所有的L进行排序,对所有的边进行排序,都为从小到大,然后对每个L,将比其小的边权的边都并在一起,计算种类数即可。

  上面的两段来源于:http://blog.csdn.net/sdj222555/article/details/7439187

  有点感慨,如果没有读懂题目,真的无法做题。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=10010,M=50010;struct node{    int u,v,w;}edge[M];bool cmp(const node &a, const node &b){    return a.w<b.w;}int f[N],r[N];int n,m,q,cnt;void init(){    for(int i=0;i<=n;i++)    {        f[i]=i;r[i]=1;    }}int Find(int x){    if(x==f[x])  return x;    return f[x]=Find(f[x]);}void Link(int x,int y){    int a=Find(x), b=Find(y);    cnt=0;    if(a!=b)    {        f[b]=a;        cnt=r[a]*r[b];        r[a]+=r[b];    }}int ans[N];struct NODE{    int id,re,num;}que[N];bool cmp1(const NODE &a,const NODE &b){    return a.num<b.num;}bool cmp2(const NODE &a,const NODE &b){    return a.id<b.id;}int main(){    //freopen("test.txt","r",stdin);    int i,j,k;    while(scanf("%d%d%d",&n,&m,&q)!=EOF)    {        init();        for(i=0;i<m;i++)            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);        for(i=0;i<q;i++)        {            scanf("%d",&que[i].num);            que[i].id=i;            que[i].re=0;        }        sort(edge,edge+m,cmp);        sort(que,que+q,cmp1);        k=0;        for(i=0;i<q;i++)        {            while(edge[k].w<=que[i].num&&k<m)            {                int a=Find(edge[k].u), b=Find(edge[k].v);                if(a==b) {k++; continue;}                else                {                    Link(edge[k].u,edge[k].v);                    que[i].re+=cnt;                    k++;                }            }            if(i>0) que[i].re+=que[i-1].re;        }        sort(que,que+q,cmp2);        for(i=0;i<q;i++)            printf("%d\n",que[i].re);    }    return 0;}

 

hdu3938 Portal 离线的并查集