PAT 1034 Head of a Gang(圖遍歷+BFS)

題目

https://www.patest.cn/contests/pat-a-practise/1034

題意:給出1000條以內的通話記錄A B和權值w,如果一個團伙人數超過2人並且通話總權值超過閾值k,令團伙裏面的自身權值的最大值爲頭目,輸出所有滿足條件的團伙的頭目,和他們團伙裏面的人數。

解題思路

數據結構

  • 鄰接表存放圖的鄰接關係,weight數組存放節點權重

    • 鄰接節點 = 它通話過的所有節點
    • 每個節點的權重 = 它所在的通話記錄時間之和
  • map<string, int>vector<string>形成雙射,爲字符串分配整數值,同時將整數值對應到字符串。

算法

用BFS實現對圖的遍歷,注意到可能有多個連通分量,因此涉及到調用多次BFS。

在BFS中,每次出隊就累加團隊人數、累加團隊總權重、更新該團隊裏的最大權重,然後將該節點的鄰接節點入隊(注意一定是未訪問過的)。

需要注意的是,輸入的路徑數N最大值爲1000,所以最多可能要2000個節點!(否則會出現測試點4的段錯誤)

AC代碼

#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 2005; //路徑數爲1000,但節點數可能爲2000!

map<string, int> getStrIndex; //字符串對應的索引
string s[maxn]; //s[1..cnt]存放索引對應的字符串
map<string, int> ans; //存放輸出結果,自動排序
int cnt = 0;

vector<int> adj[maxn]; //鄰接表
int weight[maxn]; //每個節點的權重
bool visited[maxn]; //標記每個節點是否訪問過

void BFS(int start, int &head, int &member, int &sum)
{
    queue<int> q;
    q.push(start);
    visited[start] = true;
    int out, son;
    int cur_max = 0; //最大值
    while (!q.empty())
    {
        out = q.front(); q.pop(); //隊首出隊
        member++; //羣人數累加
        sum += weight[out]; //羣總權重累加
        if (weight[out] > cur_max) //更新最大權重
        {
            cur_max = weight[out];
            head = out;
        }
        for (int i = 0; i < adj[out].size(); ++i) //鄰接節點入隊
        {
            son = adj[out][i];
            if (!visited[son]) //必須是未訪問過的
            {
                q.push(son);
                visited[son] = true;
            }
        }
    }
}

void init(int n) //初始化全局變量
{
    for (int i = 0; i < maxn; ++i)
    {
        weight[i] = 0;
        visited[i] = false;
        adj[i].clear();
    }
}

int alloc_index(const string &x) //獲得字符串s的索引
{
    if (getStrIndex[x] == 0) //新的字符串
    {
        getStrIndex[x] = ++cnt;
        s[cnt] = x;
    }
    return getStrIndex[x]; //返回索引值
}


void solve(int n, int threshold)
{
    init(n);
    string a, b;
    int w;
    for (int i = 0; i < n; ++i) //輸入
    {
        cin >> a >> b >> w;
        int idxa = alloc_index(a), idxb = alloc_index(b);
        weight[idxa] += w;
        weight[idxb] += w;
        adj[idxa].push_back(idxb); //標記鄰接
        adj[idxb].push_back(idxa);
    }
    for (int i = 1; i <= cnt; ++i)
    {
        if (!visited[i]) //出現新的連通集
        {
            int head = 0, member = 0, sum = 0;
            BFS(i, head, member, sum); //傳參調用BFS
            if (member > 2 && (sum>>1) > threshold) //羣人數大於2且羣權重大於閾值
                ans[s[head]] = member;
        }
    }
    cout << ans.size() << endl; //map自動排序
    for (auto it = ans.begin(); it != ans.end(); ++it)
        cout << it->first << ' ' << it->second << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    int n, k;
    cin >> n >> k;
    solve(n, k);
}
發佈了116 篇原創文章 · 獲贊 27 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章