zoukankan      html  css  js  c++  java
  • 洛谷 P2245 星际导航 解题报告

    P2245 星际导航

    题目描述

    sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好。为了方便起见,我们可以认为宇宙是一张有N 个顶点和M 条边的带权无向图,顶点表示各个星系,两个星系之间有边就表示两个星系之间可以直航,而边权则是航行的危险程度。

    sideman 现在想把危险程度降到最小,具体地来说,就是对于若干个询问(A, B),sideman 想知道从顶点A 航行到顶点B 所经过的最危险的边的危险程度值最小可能是多少。作为sideman 的同学,你们要帮助sideman 返回家园,兼享受安全美妙的宇宙航行。所以这个任务就交给你了。

    输入输出格式

    输入格式:

    第一行包含两个正整数N 和M,表示点数和边数。

    之后 M 行,每行三个整数A,B 和L,表示顶点A 和B 之间有一条边长为L 的边。顶点从1 开始标号。

    下面一行包含一个正整数 Q,表示询问的数目。

    之后 Q 行,每行两个整数A 和B,表示询问A 和B 之间最危险的边危险程度的可能最小值。

    输出格式:

    对于每个询问, 在单独的一行内输出结果。如果两个顶点之间不可达, 输出impossible。

    说明

    对于40% 的数据,满足N≤1000,M≤3000,Q≤1000。

    对于 80% 的数据,满足N≤10000,M≤105,Q≤1000。

    对于 100% 的数据,满足N≤105,M≤3×105,Q≤105,L≤109。数据不保证没有重边和自环。


    真是的,不爱倍增了,拍了好久啊。。

    思路:求最小生成树以后打树上倍增

    错误点:
    倍增跳到同一深度后没有判是否已经相等
    堆优化的prim应该不是每次进队都加边
    倍增同一深度后向上跳时应该先更新答案再跳(我居然可以错的这么蠢。。)


    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int N=100010;
    int head0[N],edge0[N<<1],to0[N<<1],next0[N<<1],cnt0;
    void add0(int u,int v,int w)
    {
        edge0[++cnt0]=w;to0[cnt0]=v;next0[cnt0]=head0[u];head0[u]=cnt0;
    }
    int head[N],edge[N<<1],to[N<<1],next[N<<1],cnt;
    void add(int u,int v,int w)
    {
        edge[++cnt]=w;to[cnt]=v;next[cnt]=head[u];head[u]=cnt;
    }
    int used[N],m,n,Q,dep[N],anc[N];
    void dfs(int now,int an)
    {
        used[now]=1;
        anc[now]=an;
        for(int i=head0[now];i;i=next0[i])
        {
            int v=to0[i],w=edge0[i];
            if(!used[v])
                dfs(v,an);
        }
    }
    void init()
    {
        memset(used,0,sizeof(used));
        for(int i=1;i<=n;i++)
            if(!used[i])
            {
                dfs(i,i);
                add0(0,i,0);
            }
    }
    struct node
    {
        int from,to,w;
        bool friend operator <(node n1,node n2)
        {
            return n1.w>n2.w;
        }
        node(){}
        node(int from,int to,int w)
        {
            this->from=from;
            this->to=to;
            this->w=w;
        }
    };
    priority_queue <node > q;
    void prim()
    {
        memset(used,0,sizeof(used));
        for(int i=head0[0];i;i=next0[i])
        {
            int v=to0[i],w=edge0[i];
            node tt(0,v,w);
            q.push(tt);
        }
        int cntt=0;
        while(!q.empty()&&cntt<n)
        {
            int u=q.top().to;
            if(used[u]) {q.pop();continue;}
            add(q.top().from,q.top().to,q.top().w);
            add(q.top().to,q.top().from,q.top().w);
            used[u]=1;
            cntt++;
            q.pop();
            for(int i=head0[u];i;i=next0[i])
            {
                int v=to0[i],w=edge0[i];
                if(!used[v])
                {
                    node tt(u,v,w);
                    q.push(tt);
                }
            }
        }
    }
    int f[N][21],fw[N][21];
    void dfs2(int now)
    {
        used[now]=1;
        for(int i=head[now];i;i=next[i])
        {
            int v=to[i],w=edge[i];
            if(!used[v])
            {
                f[v][0]=now;
                fw[v][0]=w;
                dep[v]=dep[now]+1;
                dfs2(v);
            }
        }
    }
    void init2()
    {
        memset(used,0,sizeof(used));
        dfs2(0);
        for(int j=1;j<=20;j++)
            for(int i=0;i<=n;i++)
            {
                f[i][j]=f[f[i][j-1]][j-1];
                fw[i][j]=max(fw[i][j-1],fw[f[i][j-1]][j-1]);
            }
    }
    void query(int x,int y)
    {
        int ans=0;
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=20;i>=0;i--)
            if(dep[f[x][i]]>=dep[y])
            {
                ans=max(ans,fw[x][i]);
                x=f[x][i];
            }
        for(int i=20;i>=0;i--)
            if(f[x][i]!=f[y][i])
            {
                ans=max(ans,max(fw[x][i],fw[y][i]));
                x=f[x][i],y=f[y][i];
            }
        if(x!=y)
            ans=max(ans,max(fw[x][0],fw[y][0]));
        printf("%d
    ",ans);
    }
    int main()
    {
        freopen("data.out","r",stdin);
        freopen("bf.out","w",stdout);
        scanf("%d%d",&n,&m);
        int u,v,w;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add0(u,v,w),add0(v,u,w);
        }
        init();
        prim();
        init2();
        scanf("%d",&Q);
        for(int i=1;i<=Q;i++)
        {
            scanf("%d%d",&u,&v);
            if(anc[u]!=anc[v])
                printf("impossible
    ");
            else
                query(u,v);
        }
        return 0;
    }
    

    2018.6.30

  • 相关阅读:
    java集合的简单用法
    数据结构
    数据结构
    数据结构
    数据结构
    软件工程第三次作业
    软件工程第三次作业
    软件工程第三次作业
    软件工程第三次作业
    Linux 开发之线程条件锁那些事
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9247625.html
Copyright © 2011-2022 走看看