UVA11354 Bond 并查集

  题意:给出一张n个点m条边的无向图, 每条边有一个危险度,有q个询问, 每次给出两个点s、t,找一条路, 使得路径上的最大危险度最小

按秩合并并查集

不能路径压缩  否则就破坏了其树形结构

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
typedef pair<int,int>pii;
//////////////////////////////////
const int N=1e6+10;

int f[N],x,y,q,n,m,siz[N],w[N];
struct Edge
{
    int u,v,w;
}edge[N];
int find1(int x)
{
    return f[x]==x?x:find1(f[x]);
}

void kruscal()
{
    sort(edge+1,edge+1+m,[](Edge a,Edge b){return a.w<b.w;});
    int cnt=0;
    rep(i,1,n)f[i]=i,siz[i]=1;
    CLR(w,0);
    rep(i,1,m)
    {
        int x=find1(edge[i].u),y=find1(edge[i].v);
        if(x==y)continue;
        if(siz[x]<siz[y])
        {
            f[x]=y;
            siz[y]=max(siz[y],siz[x]+1);
            w[x]=edge[i].w;
        }
        else
        {
            f[y]=x;
            siz[x]=max(siz[x],siz[y]+1);
            w[y]=edge[i].w;
        }
        cnt++;
        if(cnt==n-1)break;
    }
}
int c[N];
int query(int x,int y)
{
    rep(i,1,n)c[i]=-1;
    int ans=0,temp=0;
    while(1)
    {
        c[x]=temp;
        if(f[x]==x)break;
        temp=max(temp,w[x]);
        x=f[x];
    }
    while(1)
    {
        if(c[y]>=0){ans=max(ans,c[y]);break;}//lca相同时就退出
        if(f[y]==y)break;
        ans=max(ans,w[y]);
        y=f[y];
    }
    return ans;
}

int main()
{   
    int ok=0;
    while(scanf("%d%d",&n,&m)==2)
    {   
        if(ok)printf("
");
        ok=1;
        rep(i,1,m)
        scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        kruscal();
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d",&x,&y);
            printf("%d
",query(x,y));
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/11335096.html