zoukankan      html  css  js  c++  java
  • PAT甲题题解-1034. Head of a Gang (30)-并查集

    给出n和k
    接下来n行,每行给出a,b,c,表示a和b之间的关系度,表明他们属于同一个帮派
    一个帮派由>2个人组成,且总关系度必须大于k。
    帮派的头目为帮派里关系度最高的人。
    (注意,这里关系度是看帮派里边的和,而不是帮派里所有个人的总和。
    如果是按个人算的话,相当于一条边加了两次,所以应该是>2*k)
    问你有多少个合格帮派,以及每个帮派里最大的头目是谁,按字典序输出

    先并查集一下,然后统计每个帮的成员数、总关系度、以及头目

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string.h>
    #include <cmath>
    #include <map>
    
    using namespace std;
    const int maxn=(1000+5)*2;
    map<string,int> maps;
    string id_name[maxn];
    int rel[maxn]; //每个人的weight
    int vis[maxn];
    struct Gang{
        string name;
        int num;
        int tot=0;
        int maxweight=0;
        bool operator<(const Gang tmp)const{
            if(name.compare(tmp.name)<=0)
                return true;
            else
                return false;
        }
    }gang[maxn];
    //并查集
    struct UF{
        int fa[maxn];
        int num[maxn];
        void init(){
            for(int i=0;i<maxn;i++){
                fa[i]=i;
                num[i]=1;
            }
        }
        int find_root(int u){
            if(fa[u]!=u)
                fa[u]=find_root(fa[u]);
            return fa[u];
        }
        void Union(int x,int y){
            int fx=find_root(x);
            int fy=find_root(y);
            if(fx!=fy){
                fa[fy]=fx;
                num[fx]+=num[fy];
            }
        }
    }uf;
    
    int main()
    {
        char str1[20],str2[20];
        int a;
        int cnt=0;
        int n,k;
        uf.init();
        memset(rel,0,sizeof(rel));
        scanf("%d %d",&n,&k);
        for(int i=0;i<n;i++){
            cin>>str1>>str2;
            scanf("%d",&a);
            if(maps[str1]==0){
                maps[str1]=++cnt;
                id_name[cnt]=str1;
            }
            if(maps[str2]==0){
                maps[str2]=++cnt;
                id_name[cnt]=str2;
            }
            rel[maps[str1]]+=a;
            rel[maps[str2]]+=a;
            uf.Union(maps[str1],maps[str2]);
        }
        memset(vis,0,sizeof(vis));
        int gangcnt=0;
        //父亲一样的属于同一个组,建立父亲id与帮派之间的映射
        for(int i=1;i<=cnt;i++){
            int group=uf.find_root(i);
            if(!vis[group]){
                vis[group]=++gangcnt;
                gang[gangcnt].num=uf.num[group];
                gang[gangcnt].tot+=rel[i];
                gang[gangcnt].maxweight=rel[i];
                gang[gangcnt].name=id_name[i];
            }
            else{
                int id=vis[group];
                gang[id].tot+=rel[i];
                if(rel[i]>gang[id].maxweight){
                    gang[id].name=id_name[i];
                    gang[id].maxweight=rel[i];
                }
            }
        }
        sort(gang+1,gang+gangcnt+1);
        int ans=0;
        for(int i=1;i<=gangcnt;i++){
    //tot要除以2,因为一条边的weight加了2次
            if(gang[i].num>2&&gang[i].tot/2>k){
    
                ans++;
            }
        }
        printf("%d
    ",ans);
        for(int i=1;i<=gangcnt;i++){
            if(gang[i].num>2&&gang[i].tot/2>k){
                cout<<gang[i].name<<" "<<gang[i].num<<endl;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ZOJ
    Clock(数学题)
    The Lucky Week(规律)
    POJ 3233 Matrix Power Series
    POJ 1061 青蛙的约会(扩展欧几里德算法)
    2266: number
    2263: neighbor
    2269: minval(优先队列)
    HDU
    Problem 2150 Fire Game (广搜+枚举)
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/6735433.html
Copyright © 2011-2022 走看看