单点度限制最小生成树存代码
来源:互联网 发布:曾仕强预言2035知乎 编辑:程序博客网 时间:2024/06/06 10:59
Problem Description
Given a weighted graph
Algorithm
Refer to 《最小生成树问题的拓展》汪汀. Thanks to Prof. Carvalho, Lemma 1 can be proved through modeled by matchings.
Code
example:http://codeforces.com/contest/125/problem/E
#include <cstdio>#include <cstdlib>#include <algorithm>#include <utility>#include <cstring>#include <map>#include <climits>#include <queue>#include <cmath>#include <set>#include <stack>using namespace std;typedef long long LL;typedef unsigned long long ULL;typedef unsigned UI;typedef pair<int, int> PAIR;const int MAXN(5010);const int MAXE(200010);const int MAXK(100010);const int MAXL(10);const int MAXC(2);const int INF((INT_MAX - 1) / 2);const int F(0);template<typename T>inline bool checkmax(T &a, const T &b) { return b > a ? ((a = b), true) : false;}template<typename T>inline bool checkmin(T &a, const T &b) { return b < a ? ((a = b), true) : false;}template<typename T>inline T ABS(T a) { return a < 0 ? -a : a;}double dis(double x1, double y1, double x2, double y2) { return sqrt((y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1));}double dis2(double x1, double y1, double x2, double y2) { return (y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1);}struct FS { int fa[MAXN]; void init(int n) { for (int i = 0; i < n; ++i) fa[i] = i; } int find(int u) { if (fa[u] != u) fa[u] = find(fa[u]); return fa[u]; }} fs;struct E { int u, v, ti; E *next; E(int u_, int v_, int w_, E *n_) :u(u_), v(v_), next(n_) {} E(){}};int aA[MAXE / 2], bA[MAXE / 2], cA[MAXE / 2];int order[MAXE / 2];int adj[MAXN], best[MAXN], cand[MAXN];bool choose[MAXE / 2];struct G { E *first[MAXN]; E edge[MAXE], *rear; void init(int n) { memset(first, 0, sizeof(first[0])*n); rear = edge; } void addEdge(int u, int v, int ti) { rear->ti = ti; //ti存储边的索引 rear->u = u; rear->v = v; rear->next = first[u]; first[u] = rear++; } void dfs(int u, int f) { for (E *i = first[u]; i; i = i->next) { int ti = i->ti; int v = i->v; if (!choose[ti] || v == f) continue; if (u != 0) { best[v] = cA[ti]; cand[v] = ti; if (checkmax(best[v], best[u])) cand[v] = cand[u]; } else { best[v] = -INF; cand[v] = -1; } dfs(v, u); } }} g;bool cmp(int a, int b) { return cA[a] < cA[b];}vector<int> restMST(int n, int K, vector<pair<PAIR, int> > link) { //deg(v_0)=K条件下的MST, n为点数,link为无向非环边集 int m = (int)link.size(); for (int i = 0; i < m; ++i) { pair<PAIR, int> t = link[i]; aA[i] = t.first.first; bA[i] = t.first.second; cA[i] = t.second; order[i] = i; if (aA[i] > bA[i]) swap(aA[i], bA[i]); } sort(order, order + m, cmp); fs.init(n); for (int i = 0; i < m; ++i) { int ti = order[i]; choose[ti] = false; if (aA[ti] == 0) continue; int r1 = fs.find(aA[ti]), r2 = fs.find(bA[ti]); if (r1 == r2) continue; fs.fa[r2] = r1; choose[ti] = true; } int components = 0; //G-v_0形成的连通分量数 for (int i = 1; i < n; ++i){ adj[i] = -1; cand[i] = -1; if (fs.fa[i] == i) ++components; } if (components > K) return vector<int>(1, -1); int cnt = 0; for (int i = 0; i < m; ++i) { int ti = order[i]; if (aA[ti] != 0) continue; adj[bA[ti]] = ti; int r = fs.find(bA[ti]); if (cand[r] == -1) { cand[r] = 1; //这里是临时借用cand表示某个连通分量是否已经和v_0相连 choose[ti] = true; ++cnt; } } if (cnt != components) return vector<int>(1, -1); g.init(n); for (int i = 0; i < m; ++i) { if (!choose[i]) continue; g.addEdge(aA[i], bA[i], i); g.addEdge(bA[i], aA[i], i); } while (components < K) { g.dfs(0, -1); int tBest = INF, tCand; for (int i = 1; i < n; ++i) { int ti = adj[i]; if (ti == -1 || choose[ti]) continue; if (checkmin(tBest, cA[ti] - best[i])) tCand = i; } if (tBest == INF) return vector<int>(1, -1); int ti = adj[tCand]; g.addEdge(aA[ti], bA[ti], ti); g.addEdge(bA[ti], aA[ti], ti); choose[ti] = true; ti = cand[tCand]; choose[ti] = false; ++components; } vector<int> ret; for (int i = 0; i < m; ++i) if (choose[i]) ret.push_back(i); return ret;}int main() { int n, m, K; scanf("%d%d%d", &n, &m, &K); vector<pair<PAIR, int> > link; int u, v, w; for (int i = 0; i < m; ++i) { scanf("%d%d%d", &u, &v, &w); --u; --v; if (u == v) continue; link.push_back(make_pair(PAIR(u, v), w)); } vector<int> ans = restMST(n, K, link); if (ans.size() == 1 && ans[0] == -1) printf("-1\n"); else { printf("%d\n", ans.size()); bool pr(false); for (int i = 0; i < ans.size(); ++i) { if (pr) printf(" "); pr = true; printf("%d", ans[i]+1); } if(pr) printf("\n"); } return 0;}
0 0
- 单点度限制最小生成树存代码
- 最小度限制生成树
- 最小度限制生成树
- 最小度限制生成树
- 最小度限制生成树
- 最小度限制生成树
- pku1639最小度限制生成树
- Picnic Planning 最小度限制生成树
- 最小 k 度限制生成树
- 最小k度限制生成树
- 最小 k 度限制生成树
- 最小 k 度限制生成树
- POJ 1639 最小度限制生成树
- poj1639+最小k度限制生成树
- k度限制最小生成树
- 最小K度限制生成树
- 最小度限制生成树 POJ1639
- POJ 1639 Picnic Planning【度限制最小生成树】
- 设计一套缓存框架需要关注的要素
- LUA学习笔记(第5-6章)
- jenkins 入门教程(中)
- C++STL之string详讲
- 股票K线图
- 单点度限制最小生成树存代码
- iOS开发的22个诡异技巧
- Android快速屏幕尺寸适配 快速生成 res/dimens.xml
- 在centOs7虚拟机上安装vmware-tools时的报错解决
- hd 2037 今年暑假不AC(sort+结构体+贪心)
- Oracle之我见
- jenkins 入门教程(下)
- 如何在APP中集成Google账户登录
- 11. Container With Most Water