HDU4858 項目管理 算法刷題筆記

1. 題目描述

1.1. Limit

Time Limit: 2000/1000 MS (Java/Others)

Memory Limit: 32768/32768 K (Java/Others)

1.2. Problem Description

我們建造了一個大項目!這個項目有 nn 個節點,用很多邊連接起來,並且這個項目是連通的!
兩個節點間可能有多條邊,不過一條邊的兩端必然是不同的節點。
每個節點都有一個能量值。

現在我們要編寫一個項目管理軟件,這個軟件呢有兩個操作:

  1. 給某個項目的能量值加上一個特定值。
  2. 詢問跟一個項目相鄰的項目的能量值之和。(如果有多條邊就算多次,比如 aabb22 條邊,那麼詢問 aa 的時候 bb 的權值算 22 次)。

1.3. Input

第一行一個整數 T(1<=T<=3)T(1 <= T <= 3),表示測試數據的個數。
然後對於每個測試數據,第一行有兩個整數 n(1<=n<=100000)n(1 <= n <= 100000)m(1<=m<=n+10)m(1 <= m <= n + 10),分別表示點數和邊數。

然後 mm 行,每行兩個數 aabb,表示 aabb 之間有一條邊。

然後一個整數 QQ

然後 QQ 行,每行第一個數 cmdcmd 表示操作類型。如果 cmdcmd00,那麼接下來兩個數 u vu\ v表示給項目 uu 的能量值加上 v(0<=v<=100)v(0 <= v <= 100)
如果 cmdcmd11,那麼接下來一個數 uu 表示詢問 uu 相鄰的項目的能量值之和。

所有點從 11nn 標號。


1.4. Output

對每個詢問,輸出一行表示答案。


1.5. Sample Input

1
3 2
1 2
1 3
6
0 1 15
0 3 4
1 1
1 3
0 2 33
1 2

1.6. Sample Output

4
15
15

1.7. Source

BestCoder Round #1


2. 解讀

看到題目中的節點和連邊,我們很自然地會想到用圖去存儲,但是
節點最大數量是 10萬,要存一個10萬x10萬的二維數組非常容易爆內存。而從題目中我們可以發現,這個圖的連邊是比較稀疏的,所以我們可以採用鄰接表的方式進行存儲。

用鄰接表存儲了點和連邊的關係之後,我們再用一個數組去存儲每一個節點的相鄰節點能量之和。在某一個節點能量增加之後,增加所有與其相鄰的節點的能量,有查詢請求時直接輸出即可。

我查了網上的一些其他解讀,據說這裏用到了一種算法叫做分塊算法,感興趣的同學可以瞭解一下。

3. 代碼

#define mill 100010
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
int main()
{
    // test case
    int t;
    scanf("%d", &t);
    // Buffer
    long long list[mill];
    // 聲明鄰接表
    vector<int> vec_list[mill];
    for (int j = 0; j < t; j++) {
        // 清空鄰接表
        memset(vec_list, 0, sizeof(vec_list));
        // 清空Buffer
        memset(list, 0, sizeof(list));
        // 讀數據
        int n, m;
        scanf("%d %d", &n, &m);
        // 連邊
        int a, b;
        // 循環m次,讀入連邊
        for (int i = 0; i < m; i++) {
            scanf("%d %d", &a, &b);
            // ---存入ab-----------
            vec_list[a].push_back(b);
            // ---存入ba-----------
            vec_list[b].push_back(a);
        }
        // 讀取query
        // query個數
        int q;
        scanf("%d", &q);
        // query 類型
        int qType;
        // query內容
        int u, v;
        // 讀入query
        for (int i = 0; i < q; i++) {
            scanf("%d", &qType);
            if (qType == 0) {
                scanf("%d %d", &u, &v);
                // 操作query 0
                // 讀連邊
                vector<int> vec = vec_list[u];
                // 爲每個與u相連的點加v能量
                for (unsigned long k = 0; k < vec.size(); k++) {
                    list[vec[k]] += v;
                }
            } else {
                scanf("%d", &u);
                // 操作query 1
                printf("%lld\n", list[u]);
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章