多校第十场 HDU 3938 Portal(离线的并查集)

来源:互联网 发布:excel成绩分析软件 编辑:程序博客网 时间:2024/04/30 12:03

题意:定义T是2点间某条路径上的最大边权,要找出某两点间所有路径上的T的最小值,给定一个L问,满足小于等于L的min{T}的个数

 题出的挺坑爹的,读半天没读懂啥意思。

达哥说是离线的并查集,大概就是用并查集来维护图,根据边权从小到大不断往图中加边,新加的边一定满足是2点间的某路径的最大值,若2点本身不在同一连通分量上,则这条边就是所求的minT,满足它的个数就是2个连通分量的定点个数的乘积。

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int maxq=10100;const int maxn=10100;const int maxm=50500;int p[maxn],rank[maxn],cnt[maxn];//for merge-find setsint index[maxq] , que[maxq] , ans[maxq];//for queryint ind[maxm] ;//for edgestruct Edge{    int u,v,w;}edge[maxm];int find (int x){    return p[x]==x?x:p[x]=find(p[x]);}int merge (int a,int b){    int fa=find (a);    int fb=find (b);    if(fa==fb)return 0;    int t=cnt[fa]*cnt[fb];    if(rank[fa]>rank[fb])p[fb]=fa,cnt[fa]+=cnt[fb],cnt[fb]=0;    else p[fa]=fb,cnt[fb]+=cnt[fa],cnt[fa]=0;    if(rank[fa]==rank[fb])rank[fb]++;    return t;}bool cmp1 (int a,int b){    return edge[a].w<edge[b].w;}bool cmp2 (int a, int b){    return que[a]<que[b];}int main (){    int n,m,q;    int u,v,w;    freopen ("in.in","r",stdin);    freopen ("out.txt","w",stdout);    while (~scanf("%d%d%d", &n,&m,&q))    {        for (int i=0 ; i<m ; ++i)        {            scanf("%d%d%d",&u,&v,&w);            u--,v--;            edge[i].u=u;edge[i].v=v;edge[i].w=w;            ind[i]=i;        }        for (int i=0 ; i<q ; ++i)        {            scanf("%d",que+i);            index[i]=i;        }        for (int i=0 ; i<n ; ++i)            rank[i]=0,p[i]=i,cnt[i]=1;        //memset (ans , 0 ,sizeof(ans));        int tmp=0;        sort (ind , ind+m , cmp1);        sort (index , index+q , cmp2);        for (int i=0 ,j=0; i<q ; ++i)        {            while (edge[ind[j]].w<=que[index[i]] && j<m)            {                tmp+=merge(edge[ind[j]].u,edge[ind[j]].v);                ++j;            }            ans[index[i]]=tmp;        }        for (int i=0 ; i<q ; ++i)        printf("%d\n",ans[i]);    }    return 0;}