• codevs 3287 货车运输


    /*
    终于没有看题解写出了一道noip T3难度的题(虽然wmy简单点拨了一下 ^^) 
    联通所有点 路上维护最小权值 使最小权值 很像最小生成树嘛
    但是他要的是最小的最大 二分不单调似乎 所以先最大生成树建图
    这样就得到了n-1条边链接n个节点 又是维护两两节点之间的路上最小值
    很容易想到LCA 怎么维护呢 开始想想 嗯 树的规模应该不会很大 嗯
    不用倍增思想应该以跑的挺快 所以第一遍只维护了dis 表示到上面的点距离
    然后嘛 很猥琐的 a=f[a][0] 一层一层的找 既然是树了 应该也挺快的嘛
    在COGS上交A了 哈哈哈数据弱  然而在codevs上T了3个点 好吧 
    下面是85分代码 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 50010
    using namespace std;
    int n,m,q,num,head[maxn],tot,fa[maxn],f[maxn][20],dep[maxn],dis[maxn];
    struct node
    {
        int u,v,t,pre;
    }e[maxn*2];
    struct Node
    {
        int u,v,t;
    }p[maxn*2];
    int init()
    {
        int x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int cmp(const Node &x,const Node &y)
    {
        return x.t>y.t;
    }
    int find(int x)
    {
        if(x!=fa[x])fa[x]=find(fa[x]);
        return fa[x];
    }
    void Add(int from,int to,int dis)
    {
        num++;
        e[num].u=from;e[num].v=to;e[num].t=dis;
        e[num].pre=head[from];head[from]=num;
    }
    void Dfs(int now,int from,int c,int Dis)
    {
        f[now][0]=from;dep[now]=c;dis[now]=Dis;
        for(int i=head[now];i;i=e[i].pre)
          if(e[i].v!=from)
            Dfs(e[i].v,now,c+1,e[i].t);
    }
    void Get_fa()
    {
        for(int j=1;j<=17;j++)
          for(int i=1;i<=n;i++)
            f[i][j]=f[f[i][j-1]][j-1];
    }
    int LCA(int a,int b)
    {
        int ret=0x3f3f3f3f;
        if(dep[a]<dep[b])swap(a,b);
        int t=dep[a]-dep[b];
        for(int i=1;i<=t;i++)
          {
              ret=min(ret,dis[a]);
              a=f[a][0];
          }
        while(a!=b)
          {
              ret=min(ret,dis[a]);
              ret=min(ret,dis[b]);
              a=f[a][0];b=f[b][0];
          }
        return ret;
    }
    int main()
    {
        n=init();m=init();
        int x,y,z;
        for(int i=1;i<=n;i++)
          fa[i]=i;
        for(int i=1;i<=m;i++)
          {
              x=init();y=init();z=init();
              p[i].u=x;p[i].v=y;p[i].t=z;
          }
        sort(p+1,p+1+m,cmp);
        for(int i=1;i<=m;i++)
          {
              int u=p[i].u,v=p[i].v;
              int r1=find(u);int r2=find(v);
              if(r1!=r2)
                {
                    Add(u,v,p[i].t);Add(v,u,p[i].t);
                    fa[r2]=r1;
                    tot++;if(tot==n-1)break;
              }
          }
        q=init();memset(dis,127/3,sizeof(dis));
        Dfs(1,1,0,0);Get_fa();
        for(int i=1;i<=q;i++)
          {
              x=init();y=init();
              int ans=LCA(x,y);
              if(ans>=707406378)ans=-1;
              printf("%d
    ",ans);
          }
    }
    /*
    下午听wmy一说 发现可以有办法跑的飞快
    既然我们能维护i往上2^j 层是谁 我们也可以顺便维护i往上2^j 层路上的最小值
    然后 非常愉快的再找lca时顺便更新下答案就ok啦
    至于-1的情况嘛 如果建完图后不在图里的自然就到不了了
    怎么算是不在图里呢 深度为0且不是1  
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 50010
    using namespace std;
    int n,m,q,num,head[maxn],tot,fa[maxn],f[maxn][20],dep[maxn],dis[maxn][20];
    struct node
    {
        int u,v,t,pre;
    }e[maxn*2];
    struct Node
    {
        int u,v,t;
    }p[maxn*2];
    int init()
    {
        int x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int cmp(const Node &x,const Node &y)
    {
        return x.t>y.t;
    }
    int find(int x)
    {
        if(x!=fa[x])fa[x]=find(fa[x]);
        return fa[x];
    }
    void Add(int from,int to,int dis)
    {
        num++;
        e[num].u=from;e[num].v=to;e[num].t=dis;
        e[num].pre=head[from];head[from]=num;
    }
    void Dfs(int now,int from,int c,int Dis)
    {
        f[now][0]=from;dep[now]=c;dis[now][0]=Dis;
        for(int i=head[now];i;i=e[i].pre)
          if(e[i].v!=from)
            Dfs(e[i].v,now,c+1,e[i].t);
    }
    void Get_fa()
    {
        for(int j=1;j<=17;j++)
          for(int i=1;i<=n;i++)
            {
              f[i][j]=f[f[i][j-1]][j-1];
              dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]);
            }
    }
    int LCA(int a,int b)
    {
        if(a!=1&&dep[a]==0)return -1;
        if(b!=1&&dep[b]==0)return -1;
        int ret=0x3f3f3f3f;
        if(dep[a]<dep[b])swap(a,b);
        int t=dep[a]-dep[b];
        if(t)
          for(int i=0;i<=17;i++)
            if(t&(1<<i))
              {
                ret=min(ret,dis[a][i]);
                a=f[a][i];
              }
        if(a==b)return ret;
        for(int i=17;i>=0;i--)
          if(f[a][i]!=f[b][i])
            {
              ret=min(ret,dis[a][i]);
              ret=min(ret,dis[b][i]);
                a=f[a][i];b=f[b][i];
            }
        ret=min(ret,min(dis[a][0],dis[b][0]));
        return ret;
    }
    int main()
    {
        n=init();m=init();
        int x,y,z;
        for(int i=1;i<=n;i++)
          fa[i]=i;
        for(int i=1;i<=m;i++)
          {
              x=init();y=init();z=init();
              p[i].u=x;p[i].v=y;p[i].t=z;
          }
        sort(p+1,p+1+m,cmp);
        for(int i=1;i<=m;i++)
          {
              int u=p[i].u,v=p[i].v;
              int r1=find(u);int r2=find(v);
              if(r1!=r2)
                {
                    Add(u,v,p[i].t);Add(v,u,p[i].t);
                    fa[r2]=r1;
                    tot++;if(tot==n-1)break;
              }
          }
        q=init();memset(dis,127/3,sizeof(dis));
        Dfs(1,1,0,0);dis[1][0]=0x3f3f3f3f;Get_fa();
        for(int i=1;i<=q;i++)
          {
              x=init();y=init();
              int ans=LCA(x,y);
              printf("%d
    ",ans);
          }
        return 0;
    }
  • 相关阅读:
    每日随笔
    每日随笔
    每日随笔
    每日随笔
    nginx的Rewrite重写
    多台机器做动静分离
    单台机器动静分离
    四层负载均衡实践
    四层负载均衡特点
    四层负载均衡做端口转发
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5654035.html
Copyright © 2020-2023  润新知