初见安~这里是传送门:Poj P1639

Description

The Contortion Brothers are a famous set of circus clowns, known worldwide for their incredible ability to cram an unlimited number of themselves into even the smallest vehicle. During the off-season, the brothers like to get together for an Annual Contortionists Meeting at a local park. However, the brothers are not only tight with regard to cramped quarters, but with money as well, so they try to find the way to get everyone to the party which minimizes the number of miles put on everyone's cars (thus saving gas, wear and tear, etc.). To this end they are willing to cram themselves into as few cars as necessary to minimize the total number of miles put on all their cars together. This often results in many brothers driving to one brother's house, leaving all but one car there and piling into the remaining one. There is a constraint at the park, however: the parking lot at the picnic site can only hold a limited number of cars, so that must be factored into the overall miserly calculation. Also, due to an entrance fee to the park, once any brother's car arrives at the park it is there to stay; he will not drop off his passengers and then leave to pick up other brothers. Now for your average circus clan, solving this problem is a challenge, so it is left to you to write a program to solve their milage minimization problem.

矮人虽小却喜欢乘坐巨大的轿车,轿车大到可以装下无论多少矮人。某天,N(N≤20)个矮人打算到野外聚餐。为了
集中到聚餐地点,矮人A 有以下两种选择
1)开车到矮人B家中,留下自己的轿车在矮人B家,然后乘坐B的轿车同行
2)直接开车到聚餐地点,并将车停放在聚餐地。虽然矮人的家很大,可以停放无数量轿车,但是聚餐地点却最
多只能停放K辆轿车。
现在给你一张加权无向图,它描述了N个矮人的家和聚餐地点,要你求出所有矮人开车的最短总路程。

Input

Input will consist of one problem instance. The first line will contain a single integer n indicating the number of highway connections between brothers or between brothers and the park. The next n lines will contain one connection per line, of the form name1 name2 dist, where name1 and name2 are either the names of two brothers or the word Park and a brother's name (in either order), and dist is the integer distance between them. These roads will all be 2-way roads, and dist will always be positive.The maximum number of brothers will be 20 and the maximumlength of any name will be 10 characters.Following these n lines will be one final line containing an integer s which specifies the number of cars which can fit in the parking lot of the picnic site. You may assume that there is a path from every brother's house to the park and that a solution exists for each problem instance.

Output

Output should consist of one line of the form 
Total miles driven: xxx 
where xxx is the total number of miles driven by all the brothers' cars.

Sample Input

10
Alphonzo Bernardo 32
Alphonzo Park 57
Alphonzo Eduardo 43
Bernardo Park 19
Bernardo Clemenzi 82
Clemenzi Park 65
Clemenzi Herb 90
Clemenzi Eduardo 109
Park Herb 24
Herb Eduardo 79
3

Sample Output

Total miles driven: 183

Sol

真的被毒瘤到了——这么毒瘤的题竟然作为考试的第一题,太打击人了好吧……

首先这个题可以翻译成这个意思——求出一颗无向图的最小生成树,满足Park节点的度数<=限定度数,也就是停放的车的数量

很好证明——因为假设点u的人开车一路到Park,这一路上的所有矮人坐同一辆车,这就是一条Park的度;并且因为要走最短的路,如果存在别的点的矮人到达了点u而不走u到Park的路径和u同乘一辆车,那么走的就不是最短路了。而走同一条路,就相当于走的边只算一次了,所以是求最小生成树。并且在求树的前提下,每个点都是连通的。

因为节点Park限定了度数,所以我们只能分离开考虑。先在删去Park点过后的各个连通块内求出最小生成树,然后开始考虑从各个连通块向Park连边。每个连通块至少要连一条边,我们就考虑Park连到这个连通块的最短的那条边。【在上述证明下,连该连通块内的任意一点效果都一样,所以我们只考虑从边权】。

而后,我们假设规定度数为K,现在有tot个连通块。【题目保证有解,所以一定有tot <= K】也就是说我们还有K - tot条边可以连。这时候就可以替换掉一些边——设点u在它的连通块内最小生成树上连出去的边权为w1,而存在从Park直接连到点u的边边权为w2且w2 < w1,那么我们就可以替换掉w1的那条边,累计的答案。当然,我们要找w1和w2差值最大的边进行替换。所以我们还需要预处理出一个量——点u到Park路径上的最大边权。【这里本意是不考虑与Park相连的边,但是就算考虑了,我们也可以因为差值的意义判定而筛掉的。】因为我们此时的替换操作是在改变我们的这个图,每次的最大边权都在改变,所以每次我们都要树形dp求一边最大边权,并且用一个bool矩阵记录这条边我们是否选用

最后输出答案即可。

实现起来有点恶心……因为字符串还要映射处理一下。

感觉自己的代码还是比较简洁了吧……我看的题解的都是100+的样子……【我的不到90行!!】

#include<iostream>
#include<map>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxn 25
using namespace std;
map<string, int> mp;
string u, v;
int m, n = 0, K, w[25][25], ed, tot, bridge[25], point[25];
int ans = 0;
bool in[25][25];
struct edge {int u, v, w;bool operator < (const edge &x) const {return w < x.w;}
}e[maxn << 4], dp[maxn];int fa[maxn];
int get(int x) {return x == fa[x]? x : fa[x] = get(fa[x]);}void Kruskal() {register int u, v;for(int i = 1; i <= n; i++) fa[i] = i;for(int i = 1; i <= m; i++) {u = e[i].u, v = e[i].v;if(u == ed || v == ed) continue;//不和Park连边 if(get(u) == get(v)) continue;fa[get(u)] = get(v); ans += e[i].w;in[u][v] = in[v][u] = true;//标记选中 }
}void dfs(int u, int pre) {for (int i = 1; i <= n; i++) {if (i == pre || !in[u][i] || i == ed) continue;if (dp[u].w > w[u][i]) dp[i] = dp[u];else dp[i].u = u, dp[i].v = i, dp[i].w = w[u][i];dfs(i, u);}
}int main() {ios::sync_with_stdio(false);memset(w, 0x3f, sizeof w);cin >> m;for(int i = 1; i <= m; i++) {cin >> u >> v;if(!mp.count(u)) mp[u] = ++n;if(!mp.count(v)) mp[v] = ++n;if(u == "Park") ed = mp[u]; else if(v == "Park") ed = mp[v];//ed记录Park的编号 cin >> w[mp[u]][mp[v]] , w[mp[v]][mp[u]] = w[mp[u]][mp[v]];e[i].u = mp[u], e[i].v = mp[v], e[i].w = w[mp[u]][mp[v]];}sort(e + 1, e + 1 + m);Kruskal();//Kruskal求各个连通块内的最小生成树 memset(bridge, 0x3f, sizeof bridge);//bridge[i]为从Park到连通块 i的最短边边权 for(int i = 1; i <= n; i++) if(fa[i] == i) tot++;//tot记录连通块数量【这里算了Park,下文解释 for(int i = 1; i <= n; i++)if(w[ed][i] < bridge[get(i)])//记录Park到连通块最短变边并标记是哪个点 bridge[get(i)] = w[ed][i], point[get(i)] = i;for(int i = 1; i <= n; i++) //累加ans if(point[i]) ans += w[ed][point[i]], in[ed][point[i]] = in[point[i]][ed] = true;cin >> K;for(int i = tot; i <= K; i++) {//因为tot如果没有计上Park,那么这里就要+1,所以就算上了。 memset(dp, -1, sizeof dp);//每次都重新跑一遍树形dp的 dfs(ed, -1);register int minedge = -(0x3f3f3f3f), minpoint;//minnedge为差值,minpoint为差值最大的点 for(int j = 1; j <= n; j++) {//替换点j到Park的边,找最大差值的替换 if(minedge < dp[j].w - w[ed][j] && j != ed)minedge = dp[j].w - w[ed][j], minpoint = j;}if(minedge <= 0) break;//ans减去这个差值已经没有意义了 in[ed][minpoint] = in[minpoint][ed] = 1;//更改边的选择情况 in[dp[minpoint].u][dp[minpoint].v] = in[dp[minpoint].v][dp[minpoint].u] = 0;ans -= minedge;//ans减去这个差值 }printf("Total miles driven: %d\n", ans);return 0;
}

超级毒瘤……思路比较简单,但是码起来就会发现会开很多变量,就越写越乱了…………

迎评:)
——End——

Poj·Picnic Planning相关推荐

  1. POJ 1639 Picnic Planning:最小度限制生成树

    题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...

  2. Picnic Planning POJ - 1639(度限制生成树)

    解题报告 题意理解 给定一张N个点,M个边的无向图,求出无向图的一颗最小生成树,但是我们要求一号节点的入度不可以超过给定的整数S 也就是一个最小生成树,要求它的一号节点,最多只能和S个节点相连. 思路 ...

  3. pku 1639 Picnic Planning 最小度限制生成树

    http://poj.org/problem?id=1639 题意: 见黑书. 思路: 最小限制树模板题: #include <iostream> #include <cstdio& ...

  4. 【题解】poj1639[2018.8.24校赛 最小生成树 A]Picnic Planning 最小度限制生成树

    题目链接 Description The Contortion Brothers are a famous set of circus clowns, known worldwide for thei ...

  5. POJ1629:picnic planning

    题目描述 矮人虽小却喜欢乘坐巨大的轿车,轿车大到可以装下无论多少矮人.某天,N(N≤20)个矮人打算到野外聚餐.为了 集中到聚餐地点,矮人A 有以下两种选择 1)开车到矮人B家中,留下自己的轿车在矮人 ...

  6. poj1639 Picnic Planning 最小度数限制生成树

    题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...

  7. 《算法竞赛进阶指南》0x62 T2 Picnic Planning

    题目传送门 题目描述 一群小丑演员,以其出色的柔术表演,可以无限量的钻进同一辆汽车中,而闻名世界. 现在他们想要去公园玩耍,但是他们的经费非常紧缺. 他们将乘车前往公园,为了减少花费,他们决定选择一种 ...

  8. 【转载】图论 500题——主要为hdu/poj/zoj

    转自--http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...

  9. poj pku图论、网络流入门题总结、汇总

    poj pku图论.网络流入门题总结.汇总 分类: acm图论 2010-08-25 18:49 243人阅读 评论(0) 收藏 举报 网络算法networkgraphconstructioninte ...

最新文章

  1. MongoDB(一):安装
  2. 第二十六讲 有特殊特征值的微分方程组
  3. tableau实战系列(四十七)-Tableau快速生成可视化视图
  4. 基于链表的快速排序C语言,双向链表的快速排序算法,编译通过,程序会崩溃,求助一下各位...
  5. 状态机学习(二)解析INI文件
  6. UEditor1.2.6.0在.net环境下使用
  7. 大数据(9) - Flume的安装与使用
  8. asp.net 2.0 防止密码框被清空的解决方案
  9. 十大经典排序算法(动图演示)-转载
  10. CTreeCtrl 类的InsertItem成员函数
  11. 【工具】在idea中使用svn
  12. 一次函数的斜率公式_一次函数斜率公式是什么?
  13. 数据结构导论(第一章概论)
  14. Oracle函数——COALESCE
  15. 火车售票系统(设计模式分析)
  16. 新兴基金经理凯瑟琳·伍德ARKK基金在 2022 年初遭受新的打击
  17. spark的fold函数理解
  18. [Python3]利用tkinter为数独计算器编写GUI
  19. iOS app跳转微信小程序失败 报bad_param
  20. 报错:表达式必须含有常量值

热门文章

  1. 自己拍摄的视频剪辑时如何消音?
  2. AD PCB 错误检查
  3. 亚里士多德的运动观念以及伽利略对它的批评
  4. 女生学java好找工作吗?
  5. darkdays手游服务器维修,darkdays
  6. iconfont添加图标的小白操作
  7. 虎年大吉,虎虎生威!
  8. 全球与中国智能火灾报警器市场现状及未来发展趋势
  9. ccmt2019-0511-语料的预处理
  10. php写彩票中奖代码,php实现自定义中奖项数和概率的抽奖函数示例