whuoj 1566 Spanning Tree (动态MST,简单)
来源:互联网 发布:淘宝优惠券在哪里领取 编辑:程序博客网 时间:2024/06/06 17:31
题意:
G是一个无向连通图。向G中加Q次边,求出每次加边后MST的权值。
思路:
该问题属于“动态最小生成树问题”,关于该问题,有几种高效算法。。
不过,因为这里数据规模不大,我们用稍微暴力一点的方法就能过了。
如果修改了一条原本不在MST中的边的值,或者新加入一条边,那么该边就有可能取代MST中的一条边。
将这条边加入MST中,会得到一个环,去掉环上最大的边,就是新的MST。
证明一下,去掉环上的任意一条边,所得的还是原图的一颗生成树。
现在,在环上删去一条边,仍然是连通的,所以还是一个连通图,由于有n-1条边,所以是生成树。
我们可以用邻接表存生成树,则找环是O(n)的。同时用邻接矩阵快速判断某条边是否在MST中
int e[Maxn+5][Maxn+5], mst[Maxn+5][Maxn+5], vis[Maxn+5], sav[3];int n, m, q, totWeight;vector<int> g[Maxn+5];struct UnionFind { int pa[Maxn+5]; void init() { for (int i=1;i<=n;++i) pa[i] = i; } int find(int x) { return x == pa[x] ? x : pa[x] = find(pa[x]); } int Union(int x, int y) { int px = find(x), py = find(y); if (px != py) { pa[px] = py; return 1; } return 0; }};UnionFind unionFind;bool cmp(const pair<int, int> &lhs, const pair<int, int> &rhs) { return e[lhs.first][lhs.second] < e[rhs.first][rhs.second];}void print_mst() { cout << "mst:\n"; for (int i=1;i<=n;++i) for (int j=i+1;j<=n;++j) if (mst[i][j]) {cout << i << ' ' << j << ' ' << e[i][j] << endl;}}void print_g() { for (int i=1;i<=n;++i) { int sz = g[i].size();cout << "g " << i << ": ";for (int j=0;j<sz;++j) cout <<g[i][j] << ' ';cout << endl; }}void MST() { for (int i=1;i<=n;++i) g[i].clear(); vector<pair<int, int> > E; for (int i=1;i<=n;++i) for (int j=i+1;j<=n;++j) if (e[i][j] != -1) { E.push_back(make_pair(i, j)); } sort(E.begin(), E.end(), cmp); unionFind.init(); totWeight = 0; for (int i=0;i<E.size();++i) { int x = E[i].first, y = E[i].second; if (unionFind.Union(x, y)) { totWeight += e[x][y]; mst[x][y] = mst[y][x] = 1; } } rep(i, 1, n) rep(j, i+1, n) if (mst[i][j]) { g[i].push_back(j); g[j].push_back(i); } //print_mst(); //print_g();}int isFind, inCircle;void dfs(int fa, int cur) { vis[cur] = 1; int sz = g[cur].size(), i; for (int k=0;k<sz && !isFind;++k) if ( (i = g[cur][k]) != fa) { if (vis[i]) { // find circle isFind = 1; inCircle = i; sav[0] = cur;sav[1] = i;sav[2] = e[cur][i]; break; } dfs(cur, i); if (isFind && inCircle && e[cur][i] > sav[2]) { sav[0] = cur;sav[1] = i;sav[2] = e[cur][i]; } } if (inCircle == cur) inCircle = 0;}void try_to_replace(int ai, int bi, int wi) { memset(vis, 0, sizeof(vis)); g[ai].push_back(bi); g[bi].push_back(ai); e[ai][bi] = e[bi][ai] = wi; mst[ai][bi] = mst[bi][ai] = 1; isFind = 0; inCircle = 0; dfs(-1, 1); //assert(isFind); if (sav[2] > wi) { // replace mst[sav[0]][sav[1]] = mst[sav[1]][sav[0]] = 0; totWeight += wi - sav[2]; vector<int>::iterator it; for (it = g[sav[0]].begin();it != g[sav[0]].end();++it) if (*it == sav[1]) { g[sav[0]].erase(it);break; } for (it = g[sav[1]].begin();it != g[sav[1]].end();++it) if (*it == sav[0]) { g[sav[1]].erase(it);break; }#if 0 cout << "insert: " << ai << ' ' << bi << ' ' << wi << endl; cout << "delete: " << sav[0] << ' ' << sav[1] << ' ' << sav[2] << endl; print_mst(); print_g();#endif } else { // do nothing mst[ai][bi] = mst[bi][ai] = 0; vector<int>::iterator it; for (it = g[ai].begin();it != g[ai].end();++it) if (*it == bi) { g[ai].erase(it);break; } for (it = g[bi].begin();it != g[bi].end();++it) if (*it == ai) { g[bi].erase(it);break; } }}int main(){#ifndef ONLINE_JUDGE freopen("input.in", "r", stdin);#endif //SPEED_UP int ai, bi, wi; while (scanf("%d%d%d", &n, &m, &q) != EOF) { memset(e, -1, sizeof(e)); memset(mst, 0, sizeof(mst)); for (int i=1;i<=m;++i) { scanf("%d%d%d", &ai, &bi, &wi); if (ai == bi) continue; if (e[ai][bi] == -1 || e[ai][bi] > wi) { e[ai][bi] = e[bi][ai] = wi; } } // MST MST(); for (int i=1;i<=q;++i) { scanf("%d%d%d", &ai, &bi, &wi); if (ai == bi) { printf("%d\n", totWeight);continue; } if (e[ai][bi] == -1) { try_to_replace(ai, bi, wi); } else { if (e[ai][bi] <= wi) { printf("%d\n", totWeight);continue; } if (mst[ai][bi]) { totWeight += wi - e[ai][bi]; } else { try_to_replace(ai, bi, wi); } e[ai][bi] = e[bi][ai] = wi; } printf("%d\n", totWeight); } } //print_mst(); return 0;}
0 0
- whuoj 1566 Spanning Tree (动态MST,简单)
- MST(Minimum Spanning Tree,最小生成树)
- 最小生成树(Minimal Spanning Tree MST)--《算法导论》
- 5.4.1 最小生成树(Minimum-Spanning-Tree,MST)
- MST(Kruskal’s Minimum Spanning Tree Algorithm)
- 最小生成树(Minimum-Spanning-Tree, MST)
- 朱刘算法(Directed Minimum Spanning Tree/Directed MST/Minimum Arborescence/Optimum Branchings)
- 文章标题 coderforces 609E : Minimum spanning tree for each edge (MST+LCA)
- [树链剖分+MST] CF609E. Minimum spanning tree for each edge
- 最小生成树MST(Minimum Spanning Tree)-普里姆(Prim)算法
- Minimum Spanning Tree (MST) -- Prim's Algorithm (c++实现)
- 武大oj 1566 Spanning Tree(最小生成树)
- Spanning tree
- Spanning Tree
- spanning-tree
- Codeforces 609E Minimum spanning tree for each edge【MST + LCA倍增】
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge MST+树上路径倍增
- codeforeces 609E Minimum spanning tree for each edge MST +LCA
- Oracle 数据库安装规范--database所在路径和归档目录所在路径必须分开
- dede 代码调用 参数问题
- Servlet源码解析:Session、Request以及Response
- 《淘宝技术这十年》读书笔记 (一).淘宝网技术简介及来源
- 黑马程序员-----泛型,Map集合
- whuoj 1566 Spanning Tree (动态MST,简单)
- URAL1965:Pear Trees(DP)
- 黑马程序员-----IO流
- URAL - 1786 Sandro's Biography
- [Leetcode 21, Easy] Merge Two Sorted Lists
- [笔记整理]九章算法第一章
- 黑马程序员-----网络编程
- iOS开发之关于NSTimer使用
- 黑马程序员-----正则表达式