• HDU6074 Phone Call (并查集 LCA)


    Phone Call

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
    Total Submission(s): 156    Accepted Submission(s): 67


    Problem Description
    There are n houses in Bytetown, labeled by 1,2,...,n. In each house, there is a person living here. Little Q lives in house 1. There are n1 bidirectional streets connecting these houses, forming a tree structure. In this problem, S(u,v) denotes the house set containing all the houses on the shortest path from house u to house v.

    The Bytetown's phone line network consists of m different lines. The i-th line can be expressed as 5 integers ai,bi,ci,di,wi, which means for every two different houses u and v from set S(ai,bi)S(ci,di)u and v can have a phone call costing wi dollars.



    Picture from Wikimedia Commons


    Little Q is now planning to hold a big party in his house, so he wants to make as many as possible people known. Everyone known the message can make several phone calls to others to spread the message, but nobody can leave his house.

    Please write a program to figure out the maximum number of people that can join the party and the minimum total cost to reach that maximum number. Little Q should be counted in the answer.
    Input
    The first line of the input contains an integer T(1T15), denoting the number of test cases.
    In each test case, there are 2 integers n,m(1n,m100000) in the first line, denoting the number of houses and phone lines.
    For the next n1 lines, each line contains two integers u and v, denoting a bidirectional edge between node u and v.
    For the next m lines, each line contains 5 integers ai,bi,ci,di,wi(1ai,bi,ci,din,1wi109), denoting a phone line.
    Output
    For each test case, print a single line containing two integers, denoting the maximum number of people that can join the party and the minimum total cost to reach that maximum number.
    Sample Input
    1 5 2 1 2 1 3 2 4 2 5 1 3 2 4 100 2 2 4 2 10
    Sample Output
    4 210
    Hint
    Step 1 : 1 make a phone call to 2 using line 1, the cost is 100. Step 2 : 1 make a phone call to 3 using line 1, the cost is 100. Step 3 : 2 make a phone call to 4 using line 2, the cost is 10.
    【题意】给你一棵树,然后给你M哥条件,每次给出a,b,c,d,cost,表示从a-->b,c-->d的路径中的点,可以互相到达,花费是cost,到达具有传递性 ,现在问你从1节点最多可以到达哪些节点,最小花费是多少。
    【分析】将点集合挨个合并算最小花费,这个过程类似最小生成树。考虑将花费从小到大排序,设up[i]表示i点往上深度最小的一个可能不是和i在同一个
      连通块的祖先,每次沿着up[i]跳即可。用路径压缩的并查集维护这个ff即可得到优秀的复杂度。
      
    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define met(a,b) memset(a,b,sizeof a)
    #define pb push_back
    #define mp make_pair
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5500;;
    const int M = 160009;
    const int mod = 1e9+7;
    const double pi= acos(-1.0);
    typedef pair<int,int>pii;
    int n,m,T;
    int parent[N],up[N],cnt[N];
    int dep[N],fa[N][20];
    ll w[N];
    vector<int>edg[N];
    struct man{
        int a,b,c,d;
        ll cost;
        bool operator < (const man &e)const {
            return cost<e.cost;
        }
    }q[N];
    int findFa(int x){
        return parent[x]==x?x:parent[x]=findFa(parent[x]);
    }
    int findUp(int x){
        return up[x]==x?x:up[x]=findUp(up[x]);
    }
    void dfs(int u,int f){
        fa[u][0]=f;
        for(int i=1;i<20;i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        for(int v : edg[u]){
            if(v==f)continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
        }
    }
    int LCA(int u,int v){
        int U=u,V=v;
        if(dep[u]<dep[v])swap(u,v);
        for(int i=19;i>=0;i--){
            if(dep[fa[u][i]]>=dep[v]){
                u=fa[u][i];
            }
        }
        if(u==v)return (u);
        for(int i=19;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];v=fa[v][i];
            }
        }
        return (fa[u][0]);
    }
    void Union(int x,int y,ll cost){
        x=findFa(x);y=findFa(y);
        if(x==y)return;
        parent[x]=y;
        cnt[y]+=cnt[x];
        w[y]+=w[x]+cost;
    }
    void merge(int u,int v,ll cost){
        while(1){
            u=findUp(u);
            if(dep[u]<=dep[v])return;
            Union(u,fa[u][0],cost);
            up[u]=fa[u][0];
        }
    }
    void solve(man s){
        int lca=LCA(s.a,s.b);
        merge(s.a,lca,s.cost);
        merge(s.b,lca,s.cost);
        lca=LCA(s.c,s.d);
        merge(s.c,lca,s.cost);
        merge(s.d,lca,s.cost);
        Union(s.a,s.c,s.cost);
    }
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);met(fa,0);
            for(int i=0;i<=n;i++)parent[i]=up[i]=i,cnt[i]=1,w[i]=0,edg[i].clear();
            for(int i=1,u,v;i<n;i++){
                scanf("%d%d",&u,&v);
                edg[u].pb(v);edg[v].pb(u);
            }
            for(int i=0;i<m;i++){
                scanf("%d%d%d%d%lld",&q[i].a,&q[i].b,&q[i].c,&q[i].d,&q[i].cost);
            }
            sort(q,q+m);
            dep[1]=1;dfs(1,0);
            for(int i=0;i<m;i++)solve(q[i]);
            printf("%d %lld
    ",cnt[findFa(1)],w[findFa(1)]);
        }
    }
  • 相关阅读:
    公钥,私钥和数字签名这样最好理解
    SolrCloud的官方配置方式
    由于Windows和Linux行尾标识引起脚本无法运行的解决
    python模块名和文件名冲突解决
    Linux下编译安装python3
    Storm集群的安装配置
    Linux下编译安装Apache 2.4
    SELinux的关闭与开启
    Spring MVC配置静态资源的正常访问
    SolrCloud环境配置
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/7289635.html
Copyright © 2020-2023  润新知