• hdu 2874 Connections between cities (LCA转RMQ)


    纠结了N久 的题目,终于过了,LCA转RMQ的思想

    首先,求出欧拉序列F[]以及深度序列B[],同时,用pos[]记录每一个节点第一次出现的位置(在欧拉序列中的位置);

    之后,就是LCA转化为RMQ的问题了,LCA(u,v)=F(RMQ(B,pos[u],pos[v]))

    ps:pos[u]<pos[v]:

    深度序列中,2个点之间的最小深度就是最近公共祖先

    View Code
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<math.h>
    #define MAXN 10010
    using namespace std;
    struct node
    {
    int v,w;
    node(int a=0,int b=0):v(a),w(b){}
    };
    vector<node> g[MAXN];
    int f[MAXN],dis[MAXN],n,dp[MAXN*2][20];
    int F[MAXN*2],B[MAXN*2],pos[MAXN*2],bn;
    bool vis[MAXN];
    //F[]保存dfs产生的欧拉序列,dis保存每个节点到根的距离,B[]保存与F[]对应的节点的深度,pos[]保存每一个节点在欧拉序列在第一次出现的位置
    void init()
    {
    for(int i=1;i<=n;i++)
    {
    f[i]=i;
    dis[i]=0;
    vis[i]=false;
    }
    }
    int find(int x)
    {
    if(x==f[x])
    return f[x];
    f[x]=find(f[x]);
    return f[x];
    }
    void Union(int x,int y)
    {
    int a=find(x);
    int b=find(y);
    if(a==b) return ;
    f[a]=b;
    }
    void dfs(int cur,int deep,int len)
    {
    int num=g[cur].size();
    vis[cur]=true;
    dis[cur]=len;
    F[bn]=cur;
    B[bn]=deep;
    pos[cur]=bn;
    bn++;
    for(int i=0;i<num;i++)
    {
    if(!vis[g[cur][i].v])
    {
    dfs(g[cur][i].v,deep+1,len+g[cur][i].w);
    F[bn]=cur;
    B[bn++]=deep;
    }
    }
    }
    void init_RMQ()
    {
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=bn;i++)
    dp[i][0]=i;
    for(int j=1;j<=log((double)(bn+1))/log(2.0);j++)
    {
    int limit=bn+1-(1<<j);
    for(int i=1;i<=limit;i++)
    {
    int x=dp[i][j-1];
    int y=dp[i+(1<<(j-1))][j-1];
    dp[i][j]=B[x]<B[y]?x:y;
    }
    }
    }
    int RMQ(int a,int b)//注意,RMQ返回的是深度序列的下标
    {
    if(a>b) {
    swap(a,b);
    }
    int k=(int)(log((double)(b-a+1))/log(2.0));
    int x=dp[a][k];
    int y=dp[b+1-(1<<k)][k];
    return B[x]<B[y]?x:y;
    }
    int main()
    {
    int m,k,u,v,w;
    while(scanf("%d %d %d",&n,&m,&k)==3)
    {
    init();
    for(int i=1;i<=m;i++)
    {
    scanf("%d %d %d",&u,&v,&w);
    Union(u,v);
    g[u].push_back(node(v,w));
    g[v].push_back(node(u,w));
    }
    for(int i=1;i<=n;i++)//将森林转化为树
    {
    if(f[i]==i)
    {
    g[0].push_back(node(i,0));
    g[i].push_back(node(0,0));
    }
    }
    bn=1;
    dfs(0,0,0);
    bn--;
    init_RMQ();//初始化RMQ
    while(k--)
    {
    scanf("%d %d",&u,&v);
    int x=find(u),y=find(v);
    if(x!=y){//用并查集判断是否连通
    printf("Not connected\n");
    continue;
    }
    int t=RMQ(pos[u],pos[v]);//用RMQ找出最近公共祖先
    //if(F[t]==0)俩种方式都可以判断
    //{
    // puts("Not connected");
    // continue;
    //}
    printf("%d\n",dis[u]+dis[v]-2*dis[F[t]]);
    }
    for(int i=0;i<=n;i++)
    g[i].clear();
    }
    return 0;
    }
  • 相关阅读:
    AndroidManifest.xml详细分析
    GoogleMap-------解决不能使用问题
    GoogleMap-------manifest文件配置
    GoogleMap-------Google Play services SDK的下载和配置
    css_兼容IE和FF的写法
    dede如何新建一个ajax服务端输出文件
    js用ajax和不同页面的php互相传值的方法
    js获取多个标签元素的内容,并根据元素的内容修改标签的属性
    网页上记录鼠标的点击次数和一段有用的php代码,自己学习使用
    PHP弹出提示框并跳转到新页面即重定向到新页面
  • 原文地址:https://www.cnblogs.com/nanke/p/2373241.html
Copyright © 2020-2023  润新知