2011 usp try-outs F 最小瓶颈+树剖 或 LCA

Auction of Services

题意:求途中任意2点路径上的最大边的最小值

思路:这个边一定在最小生成树上,prime标记最小生成树,树剖到rmq上求最值

AC代码:

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+7;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=2e5+100;
///http://codeforces.com/gym/101081


///FFFFFF
int siz[N],son[N],dep[N],top[N],fa[N],has[N],ran[N],sson[N],cnt;
struct Edge{
    int to, w, next, id;
    bool friend operator <(Edge a, Edge b){
        return a.w>b.w;
    }
}e[N<<1];
int tot=2,head[N<<1],vis[N<<1],wi[N];  //int to[N<<1],nex[N<<1],head[N<<1],wi[N<<1],tot=2,vis[N<<1];
int n,m,q;
void add(int u, int v, int w){
    e[tot].to=v;
    e[tot].w=w;
    e[tot].id=tot;
    e[tot].next=head[u];
    head[u]=tot++;
}

void Prime(int n){
    Edge now;
    bool mk[N]; mem(mk,0);
    priority_queue<Edge> Q;
    while(!Q.empty()) Q.pop();
    for(int i=head[1]; i; i=e[i].next) Q.push(e[i]);
    mk[1]=1, n--;
    while(n--){
        now=Q.top(); Q.pop();
        while(mk[now.to]){
            now=Q.top();
            Q.pop();
        }
        vis[now.id]=1, vis[now.id^1]=1;
        wi[now.to]=now.w;
        mk[now.to]=1;
        for(int i=head[now.to]; i; i=e[i].next){
            if(!mk[e[i].to]) Q.push(e[i]);
        }
    }
}

void dfs1(int u, int faa){
    siz[u]=1;
    fa[u]=faa;
    dep[u]=dep[faa]+1;
    for(int i=head[u]; i; i=e[i].next){
        int v=e[i].to;
        if(v==faa || vis[i]==0) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[son[u]]<siz[v]) son[u]=v;
    }
}

void dfs2(int u, int tp){
    top[u]=tp;
    has[u]=++cnt;
    ran[cnt]=u;
    if(son[u]) dfs2(son[u],tp);
    for(int i=head[u]; i; i=e[i].next){
        int v=e[i].to;
        if(v==fa[u] || v==son[u] || vis[i]==0) continue;
        dfs2(v,v);
    }
}

int mma[N][30];

struct RMQ{
    int log2[N<<1];
    void init(){
        log2[0]=-1;
        for(int i = 1; i <= n; i ++)  log2[i] = log2[i >> 1] + 1;
        for(int j = 1; j <= 25; j ++)
            for(int i = 1; i + (1 << j) <= n + 1; i ++)
                mma[i][j] = max(mma[i][j - 1], mma[i + (1 << j - 1)][j - 1]);
    }
    int query(int ql, int qr){
        int k = log2[qr - ql + 1];
        return max(mma[ql][k], mma[qr - (1 << k) + 1][k]);
    }
}rmq;

int get_ans(int u, int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans=max(ans,rmq.query(has[top[u]],has[u]));
        u=fa[top[u]];
    }
    if(u==v) return ans;
    if(dep[u]>dep[v]) swap(u,v);
    return ans=max(ans,rmq.query(has[son[u]],has[v]));
}
int main(){
    int u,v,w,a,b;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; ++i){
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    Prime(n);
    dfs1(1,1);
    dfs2(1,1);
    for(int i=1; i<=n; ++i) mma[has[i]][0]=wi[i];
    rmq.init();
    scanf("%d",&q);
    while(q--){
        scanf("%d%d",&a,&b);
        printf("%d\n",get_ans(a,b));
    }
    return 0;
}

 

posted on 2017-09-18 23:05  lazzzy  阅读(149)  评论(0编辑  收藏  举报

导航