BZOJ-2001-city城市建设-HNOI2010-CDQ分治
生活随笔
收集整理的這篇文章主要介紹了
BZOJ-2001-city城市建设-HNOI2010-CDQ分治
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
描述
給出有n個點, m條邊的無向圖, 每次修改一條邊的權值, 求修改后的最小生成樹的大小. 修改次數?≤ 50000.
分析
- 還是CDQ分治, 但是有點特殊. 目前的CDQ分治還是停留在看題解看別人代碼才理解的層面.
- 有一些邊一定在部分修改后的最小生成樹中, 這是優化的中心思想吧.
- 然后一個減少邊的操作, 一個減少點的操作. 看課件吧.
- 減少點的方法是縮點, 用并查集.
- 一開始想用全局變量d, n, m, ans代替函數參數傳遞. 后來發現因為分治的緣故這樣做是不行的.
代碼
#include #include using namespace std; typedef long long int lli;const int maxd = 20; const int maxn = 50000 + 10; const int INF = 0x3f3f3f3f;struct Node {int x, y, w, k, id;void init(int i) {id = i;scanf("%d %d %d", &x, &y, &w);}bool operator < (const Node& rhs) const {return w < rhs.w;} }A[maxd][maxn];struct Modify {int k, d;void init() {scanf("%d %d", &k, &d);} }B[maxn];struct UnionFindSet {int pa[maxn];void init(int n) {for(int i = 1; i <= n; i++) pa[i] = i;}int find(int x) {return x == pa[x] ? x : (pa[x] = find(pa[x]));} } ufs;struct CDQ {int pa[maxn], dis[maxn], pos[maxn];void init(int m) {for(int i = 1; i <= m; i++)dis[A[0][i].id] = A[0][i].w;}// cur depth : d// modify sequence : [L, R]// points : n, edges : mvoid solve(int d, int L, int R, int n, int m, lli ans=0LL) {for(int i = 1; i <= m; i++) {Node &a = A[d][i], &a2 = A[d-1][i];a = (Node) {a2.x, a2.y, dis[a2.id], 0, a2.id};pos[a.id] = i;}if(L == R) {Modify& b = B[L];A[d][pos[b.k]].w = dis[b.k] = b.d;ufs.init(n);sort(A[d]+1, A[d]+m+1);for(int i = 1; i <= m; i++) {Node& a = A[d][i];int x = ufs.find(a.x), y = ufs.find(a.y);if(x != y) {ufs.pa[y] = x;ans = ans + a.w;}}printf("%lld\n", ans);return;}// reductionfor(int i = L; i <= R; i++) A[d][pos[B[i].k]].k = 1; // tag of in {S}ufs.init(n);sort(A[d]+1, A[d]+m+1);for(int i = 1; i <= m; i++) if(A[d][i].k == 0) {Node& a = A[d][i];int x = ufs.find(a.x), y = ufs.find(a.y);if(x != y) {ufs.pa[y] = x;a.k = 2; // tag of in {T}}}// contractionfor(int i = 1; i <= m; i++)if(A[d][i].k == 1) A[d][i].w = -INF;ufs.init(n);sort(A[d]+1, A[d]+m+1);for(int i = 1; i <= m; i++) if(A[d][i].k != 0) {Node& a = A[d][i];int x = ufs.find(a.x), y = ufs.find(a.y);if(x != y) {ufs.pa[y] = x;if(a.k != 1) a.k = 3; // tag of in {T'-S}}}// rebuildufs.init(n);for(int i = 1; i <= m; i++) if(A[d][i].k == 3) {Node& a = A[d][i];int x = ufs.find(a.x), y = ufs.find(a.y);ufs.pa[y] = x;ans = ans + a.w;}int newn = 0, newm = 0;for(int i = 1; i <= n; i++) pa[i] = 0;for(int i = 1; i <= n; i++) {int x = ufs.find(i);if(!pa[x]) pa[x] = ++newn;}for(int i = 1; i <= m; i++) if(A[d][i].k != 0) {Node& a = A[d][i];int x = ufs.find(a.x), y = ufs.find(a.y);if(x != y) A[d][++newm] = (Node) {pa[x], pa[y], a.w, a.k, a.id};}int M = (L+R) >> 1;solve(d+1, L, M, newn, newm, ans);solve(d+1, M+1, R, newn, newm, ans);}} cdq;int main() {int n, m, q;scanf("%d %d %d", &n, &m, &q);for(int i = 1; i <= m; i++) A[0][i].init(i);for(int i = 1; i <= q; i++) B[i].init();cdq.init(m);cdq.solve(1, 1, q, n, m);return 0; }
總結
以上是生活随笔為你收集整理的BZOJ-2001-city城市建设-HNOI2010-CDQ分治的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ-1492-货币兑换cash-N
- 下一篇: BZOJ-2716-天使玩偶angel-