zoukankan      html  css  js  c++  java
  • lca 最大生成树 逆向思维 2018 徐州赛区网络预赛j

    题目链接 

    题意:

    有一个n*m的方格

    每个小格子之间有一道墙 给定建这道墙的价格

    要求建一些墙 使得方格内的任意两个小方格之间都只有唯一的一条路径 并且要使这个建墙方式花费最小

    现在给定q组坐标     问这对坐标的路径长度

    思路:树的性质之一是 结点之间只有唯一的一条路径

    通过建立墙来构出一条路径,也可以反过来理解,将墙全部建好,然后再删除一些墙

    这样的话 找出最大生成树 因为这样保证了建的墙的价格最优   

    然后再在最大生成树里面找  两个点的简单路径

    #include<bits/stdc++.h>
    using namespace std;
    
    
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    
    const int N  =1e6+3;
    int n,m;
    
    struct tree{
        int cnt,y[N],z[N],head[N],nxt[N];
        void clc(){
            cnt= 0 ;
            memset(y,0,sizeof(y));
            memset(z,0,sizeof(y));
            memset(head,0,sizeof(y));
            memset(nxt,0,sizeof(y));
        }
        void add(int a,int b,int c){
            y[++cnt] = b;z[cnt]=c;
            nxt[cnt] = head[a];
            head[a] = cnt;
        }
    }e,q;
    
    struct node{
        int u,v,c;
        friend bool operator < (node a,node b){
            return a.c>b.c;
        }
    };
    node edge[N];
    int all;
    
    int pre[N];
    int find(int x){
        return x==pre[x]?x:pre[x]=find(pre[x]);
    }
    bool same(int a,int b){
        return find(a)==find(b);
    }
    void Union(int a,int b){
        pre[find(a)]=find(b);
    }
    
    void krucal(){
        sort(edge,edge+all);
        for(int i=1;i<=n;++i)pre[i]=i;
        for(int i=0;i<all;++i){
            node tmp = edge[i];
            if(!same(tmp.u,tmp.v)){
                e.add(tmp.u,tmp.v,1);
                e.add(tmp.v,tmp.u,1);
                Union(tmp.u,tmp.v);
            }
        }
    }
    int dis[N],vis[N];
    int ans[N];
    int fxa;
    void dfs(int t,int pre){
        for(int i=e.head[t];i;i=e.nxt[i]){
            if(e.y[i]==pre)continue;
            dis[e.y[i]] = dis[t]+e.z[i];
            dfs(e.y[i],t);
        }
    }
    void lca(int t,int fa){
        for(int i=e.head[t];i;i=e.nxt[i]){
            if(e.y[i]==fa)continue;
            lca(e.y[i],t);
            pre[e.y[i]] = t;
        }
        vis[t]=1;
        for(int i=q.head[t];i;i=q.nxt[i]){
            if(vis[q.y[i]] && !ans[q.z[i]]){
                ans[q.z[i]] = dis[t]+dis[q.y[i]]-2*dis[find(q.y[i])];
            }
        }
    }
    
    int main(){
    
        while(cin>>n>>m){
    
            q.clc();e.clc();
            memset(ans,0,sizeof(ans));
            memset(vis,0,sizeof(vis));
            all = 0 ;
    
    
            char d[22],r[22];int v1,v2;
    
            n = n*m;
    
            for(int i=1;i<=n;++i){
                scanf("%s %d %s %d",d,&v1,r,&v2);
                if(d[0]=='D'){
                    edge[all++] = node{i,i+m,v1};
                }
                if(r[0]=='R'){
                    edge[all++] =node{i,i+1,v2};
                }
            }
            int a[4];
            int ask;
            scanf("%d",&ask);
    
            for(int i=1;i<=ask;++i){
                for(int j=0;j<4;++j)scanf("%d",&a[j]);
                int u= a[0]*m-m+a[1];int v = a[2]*m-m+a[3];
                q.add(u,v,i);q.add(v,u,i);
            }
    
            krucal();
    
            dis[1]=0;
            dfs(1,0);
    
            for(int i =1;i<=n;++i)pre[i]=i;
            lca(1,0);
    
            for(int i=1;i<=ask;++i)cout<<ans[i]<<endl;
    
        }
        return 0;
    }
  • 相关阅读:
    [kuangbin带你飞]专题十六 KMP & 扩展KMP & ManacherK
    [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher J
    [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher I
    pat 1065 A+B and C (64bit)(20 分)(大数, Java)
    pat 1069 The Black Hole of Numbers(20 分)
    pat 1077 Kuchiguse(20 分) (字典树)
    pat 1084 Broken Keyboard(20 分)
    pat 1092 To Buy or Not to Buy(20 分)
    pat 1046 Shortest Distance(20 分) (线段树)
    pat 1042 Shuffling Machine(20 分)
  • 原文地址:https://www.cnblogs.com/wjhstudy/p/9843184.html
Copyright © 2011-2022 走看看