【Bzoj3732】Network

题意

给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).

现在有 K个询问 (1 < = K < = 20,000)。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?


解析

类似于那啥货车运输,嗯,懒得倍增就打了树链剖分。


#include <cstdio>
#include <algorithm>

#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)
#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)
#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)
#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)

using std :: max;
using std :: min;

const int maxx = 15000 + 25;
const int maxm = 30000 + 25;
const int Inf = (unsigned)(-1) >> 1;

typedef int Array[maxx];

int n,m,x,y,z,num,cnt,ans,tot,t;
int head[maxx],to[maxm],nxt[maxm],w[maxm];
int Tx[maxx<<2];

Array v,top,dpt,ftr,son,size,fky,rnk;

class Edges{

    public:
        int x;
        int y;
        int v;

}a[maxm<<1];

bool cmp(Edges a,Edges b) {return a.v < b.v;}

namespace Segment_Tree{

    void modify(int i,int pos,int l,int r,int k){
        if(l == r) {Tx[i] = k;return;}
        int mid = (l+r) >> 1;
        if(pos <= mid) modify(i<<1,pos,l,mid,k);
        if(pos >  mid) modify(i<<1|1,pos,mid+1,r,k);
        Tx[i] = max(Tx[i<<1],Tx[i<<1|1]);
    }

    int Query(int i,int x,int y,int l,int r){
        if(x <= l && r <= y) return Tx[i];
        int ans = -Inf;
        int mid = (l+r) >> 1;
        if(x <= mid) ans = max(ans,Query(i<<1,x,y,l,mid));
        if(y >  mid) ans = max(ans,Query(i<<1|1,x,y,mid+1,r));
        return ans;
    }

}

namespace Kruskal{

    int find(int x){
        return x == fky[x]? x : fky[x] = find(fky[x]);
    }

}

namespace Cute{

    using namespace Segment_Tree;

    void Ins(int x,int y,int z){
        to[++num] = y;w[num] = z;nxt[num] = head[x];head[x] = num;
    }

    void Dfs(int x){
        size[x] = 1;
        for(int i=head[x];i;i=nxt[i]){
            if(to[i] == ftr[x]) continue;
            dpt[to[i]] = dpt[x] + 1;
            ftr[to[i]] = x;
            v[to[i]] = w[i];
            Dfs(to[i]);size[x] += size[to[i]];
            if(size[to[i]] > size[son[x]]) son[x] = to[i];
        }
    }

    void __Dfs(int x,int brn){
        rnk[x] = ++cnt;top[x] = brn;
        if(son[x]) __Dfs(son[x],brn);
        for(int i=head[x];i;i=nxt[i])
            if(to[i] != son[x] && to[i] != ftr[x])
                __Dfs(to[i],to[i]);
    }

    int Get(int x,int y){
        int ans = -Inf;
        while(top[x] != top[y]){
            if(dpt[top[x]] > dpt[top[y]]) std :: swap(x,y);
            ans = max(ans,Query(1,rnk[top[y]],rnk[y],1,n));
            y = ftr[top[y]];
        }
        if(rnk[x] > rnk[y]) std :: swap(x,y);
        if(x != y) ans = max(ans,Query(1,rnk[x]+1,rnk[y],1,n));
        return ans;
    }

}

using namespace Kruskal;
using namespace Segment_Tree;
using namespace Cute;

int main(){
    scanf("%d%d%d",&n,&m,&t);
    Rep( i , 1 , n ) fky[i] = i;
    Rep( i , 1 , m ) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);
    std :: sort(a+1,a+m+1,cmp);
    Rep( i , 1 , m ){
        int u = find(a[i].x),v = find(a[i].y);
        if(u != v){
            Ins(a[i].x,a[i].y,a[i].v);
            Ins(a[i].y,a[i].x,a[i].v);
            fky[u] = v;
            tot ++;
        }
        if(tot == n-1) break;
    }
    Dfs(1);__Dfs(1,1);
    Rep( i , 1 , n ) modify(1,rnk[i],1,n,v[i]);
    while( t-- ){
        scanf("%d%d",&x,&y);
        printf("%d\n",Get(x,y));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值