Uva 11354

Uva 11354

题意是给出n个点,m条边的图,并有q个询问(s,t),输出s到t的最右路径下的最大边权值。
用Kruskal先求出最小瓶颈生成树,并深搜将其转化为有根树,并在同时记录下每个点的深度和父结点。计算出anc[i][j]以及maxcost[i][j],分别表示i的第2^j级祖先,i到其第2^j级祖先的最长边长度,j=0时表示父节点。
那么存在递推关系anc[i][j]=anc[anc[i][j-1]][j-1],
maxcost[i][j]=max(maxcost[i][j-1],maxcost[anc[i][j-1]][j-1])。在n*lg(n)的时间里处理出这两个数组。
询问时,输入u,v。假设u深度比v深,先将u提升至与v同高,并在提升的过程中记录下最大边,再将u,v同时提升,直至他们有相同的父节点。具体实现见Query函数,利用二进制展开的方法,能将提升的过程在O(lgn)时间内实现。

#include<map>
#include<cmath>
#include<ctime>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<string>
#define LL long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxe=1e5+5;
const int maxn=5e4+5;
const int Inf=1e9+5;
struct Edge{
    int from, to, next, dist;
    int id;
    Edge(){}
    Edge(int a,int b,int c,int d,int e):from(a), to(b), next(c), dist(d), id(e){}
    bool operator <(const Edge &rhs)const{
        return dist<rhs.dist;
    }
};
int n, m, ecnt;
int par[maxn], rak[maxn];
int head[maxn], intree[2*maxe];
int cost[maxn];
int anc[maxn][20], maxcost[maxn][20];
int L[maxn], F[maxn];
Edge edges[2*maxe];
void Init(int n){
    ecnt=0;
    mm(head,-1);
    mm0(intree);
    mm0(maxcost);
    mm0(rak);
    mm0(cost);
    for(int i=0;i<n;i++)
        par[i]=i;
}
void Add_Edge(int u,int v,int d){
    edges[ecnt]=Edge(u, v, head[u], d, ecnt);
    head[u]=ecnt++;
}
int Find(int x){
    if(par[x]==x) return x;
    par[x]=Find(par[x]);
    return par[x];
}
void Unite(int u, int v){
    int fu=Find(u);
    int fv=Find(v);
    if(fu==fv) return;
    if(rak[fu]<rak[fv]){
        par[fu]=fv;
    }else{
        par[fv]=fu;
        rak[fu]++;
    }
}
bool Cmp(Edge a,Edge b){
    return a.id<b.id;
}
void Kruskal(){
    sort(edges,edges+ecnt);
    for(int i=0;i<ecnt;i++){
        Edge &e=edges[i];
        int u=e.from;
        int v=e.to;
        int fu=Find(u);
        int fv=Find(v);
        if(fu==fv) continue;
        else{
            intree[e.id]=1;
            intree[e.id^1]=1;
            Unite(u,v);
        }
    }
    sort(edges,edges+ecnt,Cmp);
}
void Dfs(int u,int fa,int dep){
    L[u]=dep, F[u]=fa;
    for(int i=head[u];i!=-1;i=edges[i].next)
    if(intree[i]){
        Edge &e=edges[i];
        if(e.to==fa) continue;
        cost[e.to]=e.dist;
        Dfs(e.to, u, dep+1);
    }
}
void PreProcess(){
    for(int i=0;i<n;i++){
        anc[i][0]=F[i];
        maxcost[i][0]=cost[i];
        for(int j=1;(1<<j)<n;j++)
            anc[i][j]=-1;
    }
    for(int j=1;(1<<j)<n;j++){
        for(int i=0;i<n;i++)
        if(anc[i][j-1]!=-1){
            int x=anc[i][j-1];
            anc[i][j]=anc[x][j-1];
            maxcost[i][j]=max(maxcost[i][j-1],maxcost[x][j-1]);
        }
    }
}
int Query(int p,int q){
    if(L[p]<L[q]) swap(p,q);
    int log;
    for(log=1;(1<<log)<=L[p];log++); log--;
    int ans=-Inf;
    for(int i=log;i>=0;i--)
    if(L[p]-(1<<i)>=L[q]){
        ans=max(ans, maxcost[p][i]);
        p=anc[p][i];
    }
    if(p==q) return ans;
    for(int i=log;i>=0;i--)
    if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){
        ans=max(ans, maxcost[p][i]); p=anc[p][i];
        ans=max(ans, maxcost[q][i]); q=anc[q][i];
    }
    ans=max(ans,cost[p]);
    ans=max(ans,cost[q]);
    return ans;
}
void solve(){

}
int main(){

//      freopen("matrix.in","r",stdin);//从in.txt中读取数据
//      freopen("matrix.out","w",stdout);//输出到out.txt文件
    int T;
    int u, v, d;
    int q;
    int cas=0;

    while(~scanf("%d%d",&n,&m)){
        if(cas++!=0) puts("");
        Init(n);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&u, &v, &d);
            u--, v--;
            Add_Edge(u,v,d);
            Add_Edge(v,u,d);
        }
        Kruskal();
        Dfs(0,-1,0);
        PreProcess();
        scanf("%d",&q);
        for(int i=0;i<q;i++){
            scanf("%d%d",&u,&v);
            u--, v--;
            printf("%d\n",Query(u,v));
        }
    }

    return 0;
}
发布了54 篇原创文章 · 获赞 3 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章