首页 > 其他 > 详细

P2245 星际导航

时间:2019-10-01 23:22:33      阅读:100      评论:0      收藏:0      [点我收藏+]

P2245 星际导航

和NOIP2013货车运输几乎一样

然后又双叒叕wa了

原因:

LCA初始化的循环打反了!

思路吗肥肠简单,对于原图进行最小生成树,这里用克鲁斯卡尔

可以发现所选路径一定是这两个点在生成树上的简单路径 

证明:

如果有一条更小,它就会被选进最小生成树,这不符合最小生成树的定义,故失败

然后LCA和倍增即可

代码:  

#include<bits/stdc++.h>
using namespace std;
const int N=300005;
int n,m,Q;
struct node{
    int from,to,val;
}s[N*2];
int hed[N*2],nxt[N*2],cnt=0;
int n_hed[N*2],n_nxt[N*2],n_val[N*2],n_tal[N*2];
int n_cnt=0;
int f[N];
int jump[N][25]={0};
int value[N][25]={0};
bool vis[N]={0};
int dep[N];
inline int find(int x){
    if(f[x]!=x) f[x]=find(f[x]);
    return f[x];
}
inline void unionn(int x,int y){
    int fa=find(x);
    int fb=find(y);
    if(fa!=fb) f[fa]=fb;
}
inline void addege(int x,int y,int z){
    cnt++;
    s[cnt].to=y;
    s[cnt].val=z;
    s[cnt].from=x;
    nxt[cnt]=hed[x];
    hed[x]=cnt;
}
inline void n_addege(int x,int y,int z){
    n_cnt++;
    n_tal[n_cnt]=y;
    n_val[n_cnt]=z;
    n_nxt[n_cnt]=n_hed[x];
    n_hed[x]=n_cnt;
}
inline bool cmp(node x,node y){
    return x.val<y.val;
}
inline void dfs(int u,int fa){
    vis[u]=1;
    for(int i=n_hed[u];i;i=n_nxt[i]){
        int v=n_tal[i];
        if(v==fa) continue;
        dep[v]=dep[u]+1;
        dfs(v,u);
        jump[v][0]=u;
        value[v][0]=n_val[i];
    }
}
inline int lca(int x,int y){
    int ans=0;
    if(dep[x]>dep[y]) swap(x,y);
    for(int i=20;i>=0;i--){
        if(dep[jump[y][i]]>=dep[x]){
            ans=max(ans,value[y][i]);
            y=jump[y][i];
        }
    }
    if(x==y) return ans;
    for(int i=20;i>=0;i--){
        if(jump[x][i]!=jump[y][i]){
            ans=max(ans,value[x][i]);
            ans=max(ans,value[y][i]);
            x=jump[x][i];
            y=jump[y][i];
        }
    } 
    ans=max(ans,value[x][0]);
    ans=max(ans,value[y][0]);
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        addege(x,y,z);
    }
    for(int i=1;i<=n;i++) f[i]=i;
    sort(s+1,s+cnt+1,cmp);
    for(int i=1;i<=cnt;i++){
        if(find(s[i].from)!=find(s[i].to)){
            unionn(s[i].from,s[i].to);
            n_addege(s[i].from,s[i].to,s[i].val);
            n_addege(s[i].to,s[i].from,s[i].val);
        }
    }
    //root有多个 
    for(int i=1;i<=n;i++){
        if(vis[i]==0){
            dep[i]=1;
            dfs(i,-1);
            jump[i][0]=i;
            value[i][0]=0;
        }
    }
    
    for(int i=1;i<=20;i++){
        for(int j=1;j<=n;j++){
            jump[j][i]=jump[jump[j][i-1]][i-1];
            value[j][i]=max(value[j][i-1],value[jump[j][i-1]][i-1]);

        }
    }
    scanf("%d",&Q);
    while(Q--){
        int x,y;
        scanf("%d%d",&x,&y);
        if(find(x)!=find(y)){
            printf("impossible\n");
            continue;
        }
        printf("%d\n",lca(x,y));
    }
    
    return 0;
}

 

P2245 星际导航

原文:https://www.cnblogs.com/QYJ060604/p/11616317.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!