标签:图分治
题意:给n(<=100000)个点,m条边( <=n+10),可能有重边,每个点有个值val,初识为0。
2种操作。
操作1:点x的值,加addx。
操作2:输出x点的邻点的val和。
分析:简单的优化操作1或操作2是不行的。
法一:针对点的度将图中点分为两类点。对于度大于sqrt (n)的点为重点,对于小于等于sqrt(n)的点为轻点。 重点的个数小于sqrt(n)个。针对重点和轻点分别处理。
法二:也可考虑每个点,将其邻点分类。大于该点度的点分为一类,等于该点的度的分为一类,小于该点的度的点分为一类。分别处理。
法一:
const int maxn = 100100; vector<int>v[maxn], vgt[maxn]; int d[maxn]; int val[maxn]; int sum[maxn]; int n, m; const int MM = 3333; int main () { int T; cin >> T; while (T--) { scanf("%d%d", &n, &m); memset(d, 0, sizeof(d)); memset(val, 0, sizeof(val)); memset(sum, 0, sizeof(sum)); for (int i = 1; i <= n; i++) { v[i].clear(); vgt[i].clear(); } for (int i = 0; i < m; i++) { int x, y; scanf("%d%d", &x, &y); v[x].push_back(y); v[y].push_back(x); d[x]++; d[y]++; } for (int i = 1; i <= n; i++) { for (int j = 0; j < v[i].size(); j++) { int r = v[i][j]; if (d[r] > MM) vgt[i].push_back(r); } } int Q; cin >> Q; while (Q--) { int op; int x, addx; scanf("%d", &op); if (!op) { scanf("%d%d", &x, &addx); val[x] += addx; if (d[x] <= MM) { for (int i = 0; i < vgt[x].size(); i++) { int y = vgt[x][i]; sum[y] += addx; } } } else { scanf("%d", &x); int ans = 0; if (d[x] <= MM) { for (int i = 0; i < v[x].size(); i++) { ans += val[v[x][i]]; } } else { ans += sum[x]; for (int i = 0; i < vgt[x].size(); i++) { int y = vgt[x][i]; ans += val[y]; } } printf("%d\n", ans); } } } return 0; } /** 4 3 2 1 2 1 3 6 0 1 15 0 3 4 1 1 1 3 0 2 33 1 2 3 2 1 2 1 2 6 0 1 15 1 1 0 2 15 1 1 1 3 */
const int maxn = 100100; vector<int>v[maxn], vgt[maxn], veq[maxn]; int d[maxn]; int val[maxn]; int sum[maxn]; int n, m; const int MM = 3333; int main () { int T; cin >> T; while (T--) { scanf("%d%d", &n, &m); memset(d, 0, sizeof(d)); memset(val, 0, sizeof(val)); memset(sum, 0, sizeof(sum)); for (int i = 1; i <= n; i++) { v[i].clear(); vgt[i].clear(); veq[i].clear(); } for (int i = 0; i < m; i++) { int x, y; scanf("%d%d", &x, &y); v[x].push_back(y); v[y].push_back(x); d[x]++; d[y]++; } for (int i = 1; i <= n; i++) { for (int j = 0; j < v[i].size(); j++) { int r = v[i][j]; if (d[r] > d[i]) vgt[i].push_back(r); else if (d[r] == d[i]) veq[i].push_back(r); } } int Q; cin >> Q; while (Q--) { int op; int x, addx; scanf("%d", &op); if (!op) { scanf("%d%d", &x, &addx); val[x] += addx; for (int i = 0; i < vgt[x].size(); i++) sum[vgt[x][i]] += addx; } else { scanf("%d", &x); int ans = sum[x]; for (int i = 0; i < vgt[x].size(); i++) ans += val[vgt[x][i]]; for (int i = 0; i < veq[x].size(); i++) ans += val[veq[x][i]]; printf("%d\n", ans); } } } return 0; } /** 4 3 2 1 2 1 3 6 0 1 15 0 3 4 1 1 1 3 0 2 33 1 2 3 2 1 2 1 2 6 0 1 15 1 1 0 2 15 1 1 1 3 */
hdu 4858 项目管理 图分治 (复合算法),布布扣,bubuko.com
标签:图分治
原文地址:http://blog.csdn.net/guognib/article/details/38238647