POJ 1639 Picnic Planning(有限制的最小生成树)
2017-08-23 23:56
399 查看
题目地址
题意:矮人虽小却喜欢乘坐巨大的轿车,轿车大到可以装下无论多少矮人。某天,N(N≤20)个矮人打算到野外聚餐。为了集中到聚餐地点,矮人A要么开车到矮人B家中,留下自己的轿车在矮人B家,然后乘坐B的轿车同行;要么直接开车到聚餐地点,并将车停放在聚餐地。 虽然矮人的家很大,可以停放无数量轿车,但是聚餐地点却最多只能停放K辆轿车。现在给你一张加权无向图,它描述了N个矮人的家和聚餐地点,要你求出所有矮人开车的最短总路程。
思路:其实就是有限制的最小生成树,主要的思想是把根节点先删除,使得树变成m棵子树,分别求m棵子树的最小生成树再求和,然后再找每棵生成树中与根节点相距最近的边,连上,这就成为了m度的最小生成树,然后再在各个生成树中找到可以与根节点能连接的节点,选最小的,然后因为这样加边就会导致成环,所以删除环中最长的边,这样依次下去就能构成k度最小生成树(因为该题只是不要大于k,所以如果权重不再减小就可以停止了)。
推荐:2004年国家集训队论文
题意:矮人虽小却喜欢乘坐巨大的轿车,轿车大到可以装下无论多少矮人。某天,N(N≤20)个矮人打算到野外聚餐。为了集中到聚餐地点,矮人A要么开车到矮人B家中,留下自己的轿车在矮人B家,然后乘坐B的轿车同行;要么直接开车到聚餐地点,并将车停放在聚餐地。 虽然矮人的家很大,可以停放无数量轿车,但是聚餐地点却最多只能停放K辆轿车。现在给你一张加权无向图,它描述了N个矮人的家和聚餐地点,要你求出所有矮人开车的最短总路程。
思路:其实就是有限制的最小生成树,主要的思想是把根节点先删除,使得树变成m棵子树,分别求m棵子树的最小生成树再求和,然后再找每棵生成树中与根节点相距最近的边,连上,这就成为了m度的最小生成树,然后再在各个生成树中找到可以与根节点能连接的节点,选最小的,然后因为这样加边就会导致成环,所以删除环中最长的边,这样依次下去就能构成k度最小生成树(因为该题只是不要大于k,所以如果权重不再减小就可以停止了)。
推荐:2004年国家集训队论文
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #define N 50 #define M 90010 #define LL __int64 #define inf 0x3f3f3f3f #define lson l,mid,ans<<1 #define rson mid+1,r,ans<<1|1 #define getMid (l+r)>>1 #define movel ans<<1 #define mover ans<<1|1 using namespace std; const LL mod = 1e9 + 7; map<string, int> ad; int mapp ; int len , clo , pre , fst , max_side ; int n, m, k; void init() { ad.clear(); memset(mapp, inf, sizeof(mapp)); memset(len, inf, sizeof(len));//维护最小生成树的值 memset(clo, 0, sizeof(clo));//表明是哪个子树的 memset(pre, -1, sizeof(pre));//记录前驱 memset(fst, 0, sizeof(fst));//表明加上0->i这条边去与pack连接,让最小生成树与根节点相连 } struct node { int v, cap; node() {} node(int _v, int _cap) :v(_v), cap(_cap) {} bool operator < (const node &a) const { return a.cap<cap; } }; int Prim(int src, int id) { priority_queue<node> q; while (!q.empty()) q.pop(); len[src] = 0; q.push(node(src, 0)); int ans = 0; while (!q.empty()) { node cur = q.top(); q.pop(); int u = cur.v; if (!clo[u]) { clo[u] = id;//标明是哪个子树的 ans += len[u]; for (int i = 1; i < n; i++) { if (!clo[i] && len[i] > mapp[u][i]) { pre[i] = u; len[i] = mapp[u][i]; q.push(node(i, len[i])); } } } } return ans; } void updata(int cur,int last,int maxside) {//更新两个点的最大距离 if (mapp[cur][last] == inf) { max_side[cur] = maxside; } else { max_side[cur] = max(maxside, mapp[cur][last]); } for (int i = 1; i < n; i++) { if (i != last&&mapp[cur][i] != inf && (pre[cur] == i || pre[i] == cur)) { updata(i, cur, max_side[cur]); } } } void solve() { int sum, cnt; sum = 0; cnt = 1; for(int i=1;i<n;i++){//去除了根节点park if (!clo[i]) {//如果还没有被之前的最小生成树搜到就以他为子树的根节点 sum += Prim(i, cnt++);//cnt图中的连通子图个数,即最小生成树个数 } } for (int i = 1; i < n; i++) { int id = clo[i]; if (mapp[0][i] != inf && (!fst[id] || mapp[0][i] < mapp[0][fst[id]])) { fst[id] = i;//表明加上0->i这条边去与pack连接 } } for (int i = 1; i < cnt; i++) { sum += mapp[0][fst[i]]; mapp[0][fst[i]] = mapp[fst[i]][0] = inf;//因为这些边是不能改变的所以把边删除掉 updata(fst[i], 0, 0); } k = k - cnt + 1;//剩下可以加的度 while (k--) { int tmp = 0; for (int i = 1; i <= n; i++) { if (mapp[0][i] != inf && (tmp == 0 || max_side[tmp] - mapp[0][tmp] < max_side[i] - mapp[0][i])) { tmp = i; } } if (max_side[tmp] <= mapp[0][tmp]) {//没有办法再减小了 break; } sum -= (max_side[tmp] - mapp[0][tmp]); mapp[0][tmp] = mapp[tmp][0] = inf;//加上去以后就会有环了,所以删除环中的最长边 int p = 0; for (int i = tmp; pre[i] != -1; i = pre[i]) { if (p == 0 || mapp[p][pre[p]] < mapp[i][pre[i]]) {//删除最长的边 p = i; } } pre[p] = -1; updata(tmp, 0, 0); } cout << "Total miles driven: " << sum << endl; } int main() { cin.sync_with_stdio(false); string stra, strb; int a, b, c; while (cin >> m) { init(); ad["Park"] = 0; n = 1; for (int i = 0; i < m; i++) { cin >> stra >> strb >> c; if (ad.find(stra) == ad.end()) { ad[stra] = n; a = n++; } else { a = ad[stra]; } if (ad.find(strb) == ad.end()) { ad[strb] = n; b = n++; } else { b = ad[strb]; } mapp[a][b] = min(mapp[a][b], c); mapp[b][a] = min(mapp[b][a], c); } cin >> k; solve(); } return 0; }
相关文章推荐
- POJ 1639 Picnic Planning(度限制最小生成树)
- poj_1639 Picnic Planning(度限制最小生成树)
- POJ1639 Picnic Planning —— 根节点度数有限制的最小生成树
- poj 1639 Picnic Planning 单度限制的最小生成树
- POJ 1639 Picnic Planning 【最小度限制生成树】
- 【POJ】1639 Picnic Planning 度限制最小生成树
- POJ 1639 Picnic Planning【度限制最小生成树】
- POJ 1639 Picnic Planning【度限制最小生成树】
- Picnic Planning poj 1639 k度限制生成树
- poj 1639 Picnic Planning k限制生成树问题
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
- poj 1639 Picnic Planning 最小K度限制生成树
- POJ - 1639 最小限制生成树
- poj 1639 最小度限制生成树
- Picnic Planning POJ - 1639 限制顶点度数的MST
- POJ 1639 度限制最小生成树Prim
- POJ 1639 Picnic Planning(最小度限制生成树)
- poj1639 Picnic Planning 最小度数限制生成树
- POJ 1639:Picnic Planning(最小度限制生成树)
- poj 1639 有限制的最小生成树