zoukankan      html  css  js  c++  java
  • codevs 3287 货车运输

     由于有m条边,考虑建一颗最大生成树,然后LCA求解问题。这题也是神TM多细节。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxv 40005
    #define maxe 200005
    #define maxq 30005
    using namespace std;
    int n,m,x,y,z,anc[maxv][20],mi[maxv][20],father[maxv],g[maxv],h[maxv];
    int nume=0,numt=0,q;
    bool vis[maxv],judge[maxv];
    int dis[maxv];
    struct edge
    {
    int u,v,w,nxt;
    }e[maxe],tr[maxe];
    void addedge(int u,int v,int w)
    {
    e[++nume].u=u;
    e[nume].v=v;
    e[nume].w=w;
    e[nume].nxt=g[u];
    g[u]=nume;
    }
    void addtree(int u,int v,int w)
    {
    tr[++numt].u=u;
    tr[numt].v=v;
    tr[numt].w=w;
    tr[numt].nxt=h[u];
    h[u]=numt;
    }
    bool cmp(edge x,edge y)
    {
    return x.w>y.w;
    }
    int getfather(int x)
    {
    if (x!=father[x])
    father[x]=getfather(father[x]);
    return father[x];
    }
    void unionn(int x,int y)
    {
    int r1=getfather(x),r2=getfather(y);
    father[r1]=r2;
    }
    void kruskal()
    {
    for (int i=1;i<=n;i++)
    father[i]=i;
    for (int i=1;i<=nume*2;i++)
    {
    int u=e[i].u,v=e[i].v;
    if (getfather(u)!=getfather(v))
    {
    addtree(u,v,e[i].w);
    addtree(v,u,e[i].w);
    unionn(u,v);
    judge[u]=true;
    judge[v]=true;
    }
    }
    }
    void dfs(int u)
    {
    vis[u]=true;
    for (int i=h[u];i;i=tr[i].nxt)
    {
    int v=tr[i].v;
    if (vis[v]==false)
    {
    dis[v]=dis[u]+1;
    anc[v][0]=u;
    mi[v][0]=tr[i].w;
    dfs(v);
    }
    }
    }
    int lca(int x,int y)
    {
    if (dis[x]>dis[y]) swap(x,y);
    for (int i=15;i>=0;i--)
    {
    if ((dis[anc[y][i]]>=dis[x]) && (anc[y][i]!=0))
    y=anc[y][i];
    }
    for (int i=15;i>=0;i--)
    {
    if (anc[x][i]!=anc[y][i])
    {
    x=anc[x][i];
    y=anc[y][i];
    }
    }
    if (x==y) return x;
    else return anc[x][0];
    }
    void work()
    {
    scanf("%d%d",&x,&y);
    if ((judge[x]==false) || (judge[y]==false) || getfather(x)!=getfather(y))
    printf("-1 ");
    else
    {
    int r=lca(x,y);
    int minn=99999999;
    if (x!=r)
    {
    for (int i=15;i>=0;i--)
    {
    if ((dis[anc[x][i]]>=dis[r]) && (anc[x][i]!=0))
    {
    minn=min(minn,mi[x][i]);
    x=anc[x][i];
    }
    }
    }
    if (y!=r)
    {
    for (int i=15;i>=0;i--)
    {
    if ((dis[anc[y][i]]>=dis[r]) && (anc[y][i]!=0))
    {
    minn=min(minn,mi[y][i]);
    y=anc[y][i];
    }
    }
    }
    if (minn==99999999) printf("-1 ");
    else printf("%d ",minn);
    }
    }
    int main()
    {
    memset(g,0,sizeof(g));
    memset(h,0,sizeof(h));
    memset(vis,false,sizeof(vis));
    memset(dis,0,sizeof(dis));
    memset(judge,false,sizeof(judge));
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
    scanf("%d%d%d",&x,&y,&z);
    addedge(x,y,z);
    addedge(y,x,z);
    }
    sort(e+1,e+2*m+1,cmp);
    kruskal();
    dfs(1);
    for (int e=1;e<=15;e++)
    for (int i=1;i<=n;i++)
    {
    anc[i][e]=anc[anc[i][e-1]][e-1];
    mi[i][e]=min(mi[anc[i][e-1]][e-1],mi[i][e-1]);
    }
    scanf("%d",&q);
    for (int i=1;i<=q;i++)
    work();
    return 0;
    }

  • 相关阅读:
    ●BZOJ 2669 [cqoi2012]局部极小值
    ●HDU 6021 MG loves string
    试试数学公式~
    ●BZOJ 3622 已经没有什么好害怕的了
    ●BZOJ 2560 串珠子
    ●BZOJ 4361 isn
    ●BZOJ 2393 Cirno的完美算数教室
    ●BZOJ 1042 [HAOI2008]硬币购物
    ●BZOJ 2839 集合计数
    【LG2481】[SDOI2011]拦截导弹
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5093018.html
Copyright © 2011-2022 走看看