uva 12655 (树链剖分+生成树 好题)

来源:互联网 发布:仿淘宝商城系统 编辑:程序博客网 时间:2024/05/20 05:29

题意:

给出一张图,s次询问求两点间所有路径中最大的最小值


分析:

首先看到的是一张图,看上去貌似和树无关,仔细想想求两点间路径的最小值如何求,和什么有关,首先想到能不能离线处理,这样一想之后发现其实如果我们让大边先去建图,一直到建成一棵生成树,那么是不是两点间的答案就唯一确定了,很明显是的,因为此时小边已经排除在外了,那么如果有相同权值边会不会影响结果,很明显也不会,因为我们是按照从大到小建树的,后面的边会影响前面的边,而前面的边不会影响结果,树建成之后剩下的就是树链剖分的活了。


#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 200005int e[maxn];int x[maxn],y[maxn],c[maxn],cost[maxn],val1[maxn],val2[maxn];int fir[maxn],nex[maxn],v[maxn],e_max;int son[maxn],fa[maxn],deep[maxn],siz[maxn],top[maxn],pos[maxn],tot;int s[maxn],mi[4*maxn];void init_(int n){    for(int i=1;i<=n;i++) s[i]=i;    memset(son,-1,sizeof son);    memset(fir,-1,sizeof fir);    e_max=0;    tot=0;}void add_edge(int s,int t,int c){    int e=e_max++;    cost[e]=c;    v[e]=t;    nex[e]=fir[s];    fir[s]=e;}int root(int x){    return x==s[x]?x:s[x]=root(s[x]);}bool cmp(int a,int b){    return c[a]>c[b];}void dfs1(int k,int pre,int d){    deep[k]=d;    siz[k]=1;    fa[k]=pre;    for(int i=fir[k];~i;i=nex[i])    {        int e=v[i];        if(e!=pre)        {            val1[e]=cost[i];            dfs1(e,k,d+1);            siz[k]+=siz[e];            if(son[k]==-1||siz[son[k]]<siz[e]) son[k]=e;        }    }}void dfs2(int k,int sp){    top[k]=sp;    pos[k]=tot++;    val2[pos[k]]=val1[k];    if(son[k]==-1) return ;    dfs2(son[k],sp);    for(int i=fir[k];~i;i=nex[i])    {        int e=v[i];        if(e!=fa[k]&&e!=son[k])        {            dfs2(e,e);        }    }}void init(int l,int r,int k){    if(l==r)    {        mi[k]=val2[l];        return ;    }    int mid=l+r>>1;    init(l,mid,k<<1);    init(mid+1,r,k<<1|1);    mi[k]=min(mi[k<<1],mi[k<<1|1]);}int query(int s,int t,int l,int r,int k){    if(s==l&&r==t)    {        return mi[k];    }    int mid=l+r>>1;    if(t<=mid) return query(s,t,l,mid,k<<1);    else if(s>mid) return query(s,t,mid+1,r,k<<1|1);    else return min(query(s,mid,l,mid,k<<1),query(mid+1,t,mid+1,r,k<<1|1));}int Query(int s,int t){    int ans=INF;    int f1=top[s],f2=top[t];    while(f1!=f2)    {        if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t);        ans=min(ans,query(pos[f1],pos[s],1,tot-1,1));        s=fa[f1];        f1=top[s];    }    if(s==t) return ans;    if(deep[s]>deep[t]) swap(s,t);    ans=min(ans,query(pos[s]+1,pos[t],1,tot-1,1));    return ans;}int main(){    int n,m,q;    while(scanf("%d%d%d",&n,&m,&q)!=EOF)    {        init_(n);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&x[i],&y[i],&c[i]);            e[i]=i;        }        sort(e,e+m,cmp);        for(int i=0;i<m;i++)        {            int p=e[i];            int _x=root(x[p]),_y=root(y[p]);            if(_x!=_y)            {                s[_x]=_y;                add_edge(x[p],y[p],c[p]);                add_edge(y[p],x[p],c[p]);            }        }        dfs1(1,-1,1);        dfs2(1,1);        init(1,tot-1,1);        while(q--)        {            int a,b;            scanf("%d%d",&a,&b);            int ans=Query(a,b);            printf("%d\n",ans);        }    }    return 0;}




0 0
原创粉丝点击