现在的位置: 首页 > 综合 > 正文

hdu 4750 (并差集)

2018年03月18日 ⁄ 综合 ⁄ 共 1148字 ⁄ 字号 评论关闭

题意:求出有多少个两点之间所有路径的最大边的最小值不小于t。

思路:刚开始的思路是将边排序,把所有的t也排序,然后对于每个t,将小于t的边取出来,看有多少种联通的组合,用总的组合数减去就得到了,因为写错了一个地方tle了,就怀疑算法有问题。现在想想这就是求最小生成树的过程,小boss说了,最小生成树求出来了答案就全出来了。





#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
const int N=11000;
const int inf=0x3fffffff;
using namespace std;
int f[N],head[N],num,n,m,vis[N],de[N];
struct edge
{
    int x,y,w;
}e[N*50],q[N*10];
int cmp(void const *a,void const *b)  
{  
    edge *c,*d;  
    c=(edge *)a;  
    d=(edge *)b;  
    return c->w-d->w;  
}
int amp(void const *a,void const *b)  
{  
    edge *c,*d;  
    c=(edge *)a;  
    d=(edge *)b;  
    return c->x-d->x;  
}
int find(int a)
{
    if(a!=f[a])
        f[a]=find(f[a]);
    return f[a];
}
int main()
{
    int i,k,x,y,j,sum;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
            e[i].x++;e[i].y++;
        }
        qsort(e,m,sizeof(e[0]),cmp);
        scanf("%d",&k);
        for(i=0;i<k;i++)
        {
            scanf("%d",&q[i].x);
            q[i].w=i;
        }
        qsort(q,k,sizeof(q[0]),amp);
        for(i=1;i<=n;i++)
        {f[i]=i;de[i]=1;}
        sum=n*n-n;
        for(j=0,i=0;j<k;j++)
        {
            while(sum>0&&e[i].w<q[j].x&&i<m)//sum==0时就是求出了最小生成树了
            {
                x=find(e[i].x);
                y=find(e[i].y);
                i++;//刚开始写到下面,tle了
                if(x==y)continue;
                sum-=(2*(de[x]*de[y]));
                f[x]=find(y);
                de[y]+=de[x];
            }
                q[j].y=sum;
        }
        qsort(q,k,sizeof(q[0]),cmp);
        for(i=0;i<k;i++)
            printf("%d\n",q[i].y);
    }
    return 0;
}

抱歉!评论已关闭.