ในเมืองนครแห่งหนึ่ง มีสถานที่อยู่ ที่ ได้แก่
นับจำนวน “กลุ่มอพยพปลอดภัย” โดยให้ระบุคำตอบในรูปแบบของเศษจากการหารจำนวนของ “กลุ่มอพยพปลอดภัย” ด้วย
จำนวนถนน จะเท่ากับ ซึ่งหมายความว่า Graph ที่ได้มาจะมีลักษณะเป็น Tree
เราจะเก็บว่า สำหรับแต่ละศูนย์ตำบล ถ้าเราเลือกให้หมู่บ้าน แห่งเดินทางมายังศูนย์ตำบล โดยไม่ใช้ถนนสายเดียวกันเลย เราจะนับได้กี่กลุ่ม (นับจำนวนกลุ่มอพยพปลอดภัยที่สามารถเดินทางมา ได้)
เราจะทำ Dynamic Programming on Tree บน Tree ที่ได้รับมา โดยเราจะเก็บใน array of vector (ตั้งชื่อว่า ) ว่า ถ้าเราอยู่ที่โหนด แล้ว หากเราเดินตามถนนแต่ละสายที่ติดกับโหนด (เดินตาม adjacency list) แล้ว จะมีหมู่บ้านจำนวนกี่หมู่บ้านในเส้นทางนั้น (นับจำนวนหมู่บ้านที่อยู่ใน subtree ของ แล้วเก็บไว้ใน ) นั่นคือ ขนาดของ สำหรับแต่ละ อาจจะมีขนาดไม่เท่ากันนั่นเอง
เมื่อเราได้ มาแล้ว ทีนี้ เราจะทำการ loop จาก ถึง (loop แค่ศูนย์ตำบล) แล้วจะคำนวณว่า ถ้าหากว่าเราจะนับจากศูนย์ตำบลที่ แล้ว จะมี “กลุ่มอพยพปลอดภัย” ทั้งหมดกี่กลุ่ม และเมื่อเราคำนวณครบสำหรับศูนย์ตำบลทั้ง ศูนย์แล้ว เราจะได้คำตอบออกมา
วิธีการคำนวณ:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
const int N = 1e5 + 5;
const int M = 1e5 + 5;
int n, m, ans, sz[N + M];
vector <int> adj[N + M], cnt[N + M];
void dfs(int u, int p){
sz[u] = (u <= n);
for (auto v : adj[u]) {
if (v == p) continue;
dfs(v, u);
if (sz[v] > 0) cnt[u].emplace_back(sz[v]), sz[u] += sz[v];
}
cnt[u].emplace_back(n - sz[u]);
}
int32_t main(){
cin.tie(NULL)->sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i < n + m; i++) {
int u, v; cin >> u >> v;
adj[u].emplace_back(v);
adj[v].emplace_back(u);
}
dfs(1, 1);
for (int u = n + 1; u <= n + m; u++) {
int siz = adj[u].size();
if (siz >= 4) {
int dp[siz + 1][5];
memset(dp, 0, sizeof dp);
dp[0][0] = 1;
for (int i = 1; i <= siz; i++) {
dp[i][0] = 1;
for (int j = 1; j <= 4; j++) {
dp[i][j] = dp[i - 1][j] + (dp[i - 1][j - 1] * cnt[u][i - 1]);
}
}
ans += dp[siz][4]; ans %= mod;
}
}
cout << ans;
}
หากมีข้อสงสัย comment ไว้ใต้ post ได้เลยนะครับ 🙇♂️🙇♂️
ศึกษาโจทย์เพิ่มเติมได้ที่ Fast X Fourier