您的位置:首页 > 其它

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

2011-08-15 11:14 381 查看
题意:定义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 sets
int index[maxq] , que[maxq] , ans[maxq];//for query
int ind[maxm] ;//for edge

struct 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: