b_pat_团伙头目(并查集/dfs+字符串整形互相映射)

如果 A 和 B 之间有通话,我们就说 A 和 B 是相关的。并且关联具有传递性,即如果 A 与 B 关联,B 与 C 关联,那么 A 与 C 也是关联的。
关联权重定义为两人之间所有通话的总时间长度。
一个“帮派”是一个由至少3个相互关联的人组成的群体,并且其总关联权重大于给定的阈值 K。
在每个帮派中,总权重最大的就是头目,数据保证每个帮派中总权重最大的人是唯一的。
你需要确定各个帮派以及帮派头目。

方法一:并查集


由于我们最后需要输出的信息有:每个帮派头目(string类型)、每个帮派的人数,又由于在遍历时需要存储结点编号,而给出的都是一堆字符串,所以我需要将头目的姓名和一个作为标识的id映射起来

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    static class Solution {
        int N=1005, fa[];
        List<Integer> g[];
        int find(int u) {
            if (fa[u]==u)
                return u;
            return fa[u]=find(fa[u]);
        }
        void merge(int u, int v) {
            int fu=find(u), fv=find(v);
            if (fu!=fv) {
                fa[fu]=fv;
            }
        }
        void init() {
            Scanner sc = new Scanner(new BufferedInputStream(System.in));
            int n=sc.nextInt();
            g=new ArrayList[N]; fa=new int[N];
            for (int i=1; i<N; i++) {g[i]=new ArrayList<>(); fa[i]=i;}
            sc.nextLine();
            for (int i=1; i<=n; i++) {
                String[] line = sc.nextLine().split(" ");
                for (int j=1; j<line.length; j++) {
                    g[Integer.parseInt(line[j])].add(i);
                }
            }
            for (int i=1; i<N; i++)
            for (int j=1; j<g[i].size(); j++) {
                merge(g[i].get(0), g[i].get(j));
            }
            int cnt[]=new int[N], c=0;
            for (int i=1; i<=n; i++) {
                cnt[find(i)]++;
            }
            List<Integer> ans = new ArrayList<>();
            for (int i=1; i<=n; i++) if (cnt[i]!=0) {
                ans.add(cnt[i]);
                c++;
            }
            Collections.sort(ans, (e1, e2) -> {
                return e2-e1;
            });
            System.out.println(c);
            System.out.print(ans.get(0));
            for (int i=1; i<ans.size(); i++) {
                System.out.print(" "+ans.get(i));
            }
        }
    }
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
        s.init();
    }
}

方法二:dfs

用dfs也实现了下

2020-09-29 17:00:54 更

#include<bits/stdc++.h>
using namespace std;
const int N=1e4;
unordered_map<string, int> m1;
unordered_map<int, string> m2;
vector<int> g[N];
int id,cost[N],vis[N],totCost,head,maxCost;

int dfs(int u) {
    if (cost[u]>maxCost) {
        maxCost=cost[u];
        head=u;
    }
    int cnt=1;
    vis[u]=1, totCost+=cost[u];
    for (int v : g[u]) if (!vis[v]) {
        cnt+=dfs(v);
    }
    return cnt;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n,k; cin>>n>>k;
    for (int i=0; i<n; i++) {
        string u,v;
        int w; cin>>u>>v>>w;
        if (m1.find(u)==m1.end()) m1[u]=id, m2[id++]=u;
        if (m1.find(v)==m1.end()) m1[v]=id, m2[id++]=v;
        int uID=m1[u], vID=m1[v];
        g[uID].push_back(vID), g[vID].push_back(uID);
        cost[uID]+=w, cost[vID]+=w;
    }
    vector<pair<string, int>> ans;
    for (int i=0; i<id; i++) if (!vis[i]) {
        maxCost=-1, head=0, totCost=0;
        int cnt=dfs(i);
        if (totCost>2*k && cnt>2) ans.push_back({m2[head], cnt});
    }
    sort(ans.begin(), ans.end());
    cout<<ans.size()<<'\n';
    for (auto& gang : ans) cout<<gang.first<<' '<<gang.second<<'\n';
    return 0;
}
posted @ 2020-09-11 16:14  童年の波鞋  阅读(142)  评论(0编辑  收藏  举报