题目传送门

题目描述

一群小丑演员,以其出色的柔术表演,可以无限量的钻进同一辆汽车中,而闻名世界。

现在他们想要去公园玩耍,但是他们的经费非常紧缺。

他们将乘车前往公园,为了减少花费,他们决定选择一种合理的乘车方式,可以使得他们去往公园需要的所有汽车行驶的总公里数最少。

为此,他们愿意通过很多人挤在同一辆车的方式,来减少汽车行驶的总花销。

由此,他们可以很多人驾车到某一个兄弟的家里,然后所有人都钻进一辆车里,再继续前进。

公园的停车场能停放的车的数量有限,而且因为公园有入场费,所以一旦一辆车子进入到公园内,就必须停在那里,不能再去接其他人。

现在请你想出一种方法,可以使得他们全都到达公园的情况下,所有汽车行驶的总路程最少。

输入格式

第一行包含整数 n,表示人和人之间或人和公园之间的道路的总数量。

接下来 n 行,每行包含两个字符串 A、B 和一个整数 L,用以描述人 A 和人 B 之前存在道路,路长为 L,或者描述某人和公园之间存在道路,路长为 L。

道路都是双向的,并且人数不超过 20,表示人的名字的字符串长度不超过 10,公园用 Park 表示。

再接下来一行,包含整数 s,表示公园的最大停车数量。

你可以假设每个人的家都有一条通往公园的道路。

输出格式

输出 Total miles driven: xxx,其中 xxx 表示所有汽车行驶的总路程。

输入样例:

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

输出样例:

Total miles driven: 183

题解

考虑建图问题,由于边连接的是人名,即字符串,所以我们可以拿map映射人名给予下标,然后来用邻接矩形存边
这道题涉及到一些超出最小生成树范畴的思想,我们需要考虑删除1节点后以及与1节点相关的边之后,无向图会被分为多少个连通块,假设为T,我们首先在每一个连通块之间跑最小生成树,建立T+1棵树(1表示1号根)
我们将这T棵树中的一个节点与1号节点用一条边连接(这条边的权值应最小),于是一棵基本的树就建成了
这时考虑最优性,对于每个连通块内部,边权最小,对于每个连通块到1号节点之间,边权最小
瑕疵在于有些连通块内部的边,我们可以将其替换为连接1号点和连通块内部一点的边
这个操作最多进行S−TS-TS−T次,因为1号节点连接的边不能超过SSS条
考虑用(1,x)(1,x)(1,x)代替xxx到111的路径上权值最大的边,每次我们找出一对能使权值和减少的更多的边进行修改,如果无法进行更优的更改,我们就直接放弃之后的修改,break跳出循环,具体的细节见代码

code
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
map<string,int> mp;
map<pair<int,int>,bool> ff;
int f[N][N],vis[N],fa[N];
int n,s,cnt,tot;
struct node
{int u,v,w;
}edge[N];
bool cmp(node x,node y)
{return x.w<y.w;
}
void dfs(int x)
{for(int i=2;i<=tot;i++)if(f[x][i]&&!vis[i]){vis[i]=cnt;dfs(i);}
}
int U[N],V[N],dis[N];
void dfs1(int x,int fa)
{for(int i=2;i<=tot;i++){if(i==fa||!ff[make_pair(x,i)]) continue;if(dis[i]==-1){if(dis[x]>f[x][i]) U[i]=U[x],V[i]=V[x],dis[i]=dis[x];else U[i]=x,V[i]=i,dis[i]=f[x][i];}dfs1(i,x);}
}
int get(int x)
{if(x==fa[x]) return x;return fa[x]=get(fa[x]);
}
int main()
{scanf("%d",&n);mp["Park"]=tot=1;int t=0;for(int i=1;i<=n;i++){string a,b;int c;cin>>a>>b;scanf("%d",&c);if(!mp[a]) mp[a]=(++tot);//map映射 if(!mp[b]) mp[b]=(++tot);edge[++t].u=mp[a];//链式前向星存边 edge[t].v=mp[b];edge[t].w=c;f[mp[a]][mp[b]]=f[mp[b]][mp[a]]=c;//邻接矩阵连边 }scanf("%d",&s);for(int i=2;i<=tot;i++)//确定连通块的个数以及每个的大小 if(!vis[i]){vis[i]=++cnt;dfs(i);}sort(edge+1,edge+1+t,cmp);//对边权排序 int ans=0;for(int i=1;i<=n;i++) fa[i]=i;//并查集初始化 for(int i=1;i<=t;i++)//连通块内部连边 {int fx=get(edge[i].u),fy=get(edge[i].v);if(fx==1||fy==1||fx==fy) continue;fa[fx]=fy;ans+=edge[i].w;ff[make_pair(edge[i].u,edge[i].v)]=1;ff[make_pair(edge[i].v,edge[i].u)]=1;}for(int i=1;i<=cnt;i++)//连接1号节点 {int now=1e9,st=0;for(int j=2;j<=tot;j++)if(vis[j]==i)if(now>f[1][j]&&f[1][j]){now=f[1][j];st=j;}ans+=now;ff[make_pair(1,st)]=ff[make_pair(st,1)]=1;}int T=cnt;for(int i=T+1;i<=s;i++)//将连通块内部边改为与1节点相连的边 {int now=0,id;memset(U,0,sizeof(U));memset(V,0,sizeof(V));memset(dis,-1,sizeof(dis));dfs1(1,-1);for(int j=2;j<=tot;j++)if(now<dis[j]-f[1][j]&&f[1][j]) now=dis[j]-f[1][j],id=j;if(now<=0) break;ans-=now;ff[make_pair(U[id],V[id])]=0;ff[make_pair(1,id)]=ff[make_pair(id,1)]=1;}printf("Total miles driven: %d",ans);return 0;
}

《算法竞赛进阶指南》0x62 T2 Picnic Planning相关推荐

  1. 《算法竞赛进阶指南》打卡-基本算法-AcWing 93. 递归实现组合型枚举:递归与递推、dfs、状态压缩

    文章目录 题目解答 题目链接 题目解答 分析: 此题和笔者另一篇博文很像,只不过是限定了个数.<算法竞赛进阶指南>打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归.二进 ...

  2. 《算法竞赛进阶指南》数论篇

    <算法竞赛进阶指南>数论篇(1)-最大公约数,素数筛,欧拉函数,同余,欧拉定理,BSGS <算法竞赛进阶指南>数论篇(1)-最大公约数,素数筛,欧拉函数,同余,欧拉定理,BSG ...

  3. 《算法竞赛进阶指南(by 李煜东)》习题题解 集合

    又是笔者给自己挖的大坑. 这里是李煜东所著<算法竞赛进阶指南(by 李煜东)>的习题题解集合. 有任何错误请在对应文章下反馈或联系 nicest1919@163.com ,谢谢 qwq 从 ...

  4. CH5202 自然数拆分Lunatic版(算法竞赛进阶指南,完全背包)

    算法竞赛进阶指南,278页,完全背包 本题要点: 1.把完全背包的代码改改即可.常规的完全背包: 有n个物品,每个物品的体积是v[i], 价值是w[i], 求装到大小为m的大背包,能获得的最大价值(每 ...

  5. 中位数--《算法竞赛进阶指南》(货仓选址和七夕祭问题详解)

    中位数 今天又和大家见面了啦~ 依旧是 <算法竞赛进阶指南>的学习哦~ 中位数(Median)又称中值,统计学中的专有名词,是按顺序排列的一组数据中居于中间位置的数,代表一个样本.种群或概 ...

  6. 金字塔(算法竞赛进阶指南)

    虽然探索金字塔是极其老套的剧情,但是有一队探险家还是到了某金字塔脚下. 经过多年的研究,科学家对这座金字塔的内部结构已经有所了解. 首先,金字塔由若干房间组成,房间之间连有通道. 如果把房间看作节点, ...

  7. AcWing 122. 糖果传递【贪心】【《算法竞赛进阶指南》,微软面试题 , HAOI2008】

    AcWing 122. 糖果传递 一.题目链接 二.题目分析 (一)算法标签 (二)解题思路 三.AC代码 四.其它题解 一.题目链接 AcWing 122. 糖果传递 进阶题目 AcWing 105 ...

  8. 算法竞赛进阶指南 骑士放置

    4: 最大独立集 :选出最多的点,使得选出的点之间没有边. 求最大独立集:选出最小的点可以破坏所有的边 <==>最小点覆盖 <==>最大匹配数. 假设最大匹配数为m,共有n个点 ...

  9. 算法竞赛进阶指南 萌新入门!

    算法竞赛进阶指南 文章目录 算法竞赛进阶指南 前言 一.介绍本书 二.如何阅读本书 三.总结 **笔记思路和结构 ** 算法竞赛进阶指南 这篇文章就简单的写一下吧! 前言 ​ 作为一个想要入坑的算法的 ...

  10. 算法竞赛进阶指南0x3A 博弈论之SG函数

    算法竞赛进阶指南0x3A 博弈论之SG函数

最新文章

  1. 下载、安装、配置 java jdk1.8
  2. 牛逼!硬核图解 Tomcat 整体架构
  3. 如何打开.npz文件
  4. 重建DC的DNS区域
  5. 【C 语言】字符串拷贝 ( 指针使用前判空 | while 空语句 )
  6. UART, SPI, IIC的详解及三者的区别和联系
  7. 计算机丢失wininet,win7系统启动程序提示因为计算机中丢失wininet.dll的解决方法...
  8. java集合根据值排序_Java 8:对集合中的值进行排序
  9. ORA-01033 的解决
  10. keyshot分辨率多少合适_分辨率单位及换算详解
  11. android按钮添加音效,Android中为按钮设置点击音效
  12. android 视频画面切割,安卓手机如何剪裁视频 手机视频裁剪多余部分
  13. 提供一个中国身份证号码判断的类
  14. UE4:浅谈什么是GamePlay框架
  15. GHHHG全球海岸线提取
  16. nohup不输出nohup.out日志信息(nohup: appending output to ‘nohup.out‘)
  17. html5+植物大战僵尸,HTML5 Canvas植物大战僵尸 - 鳄梨射手
  18. html5 选择金额样式,[JavaScript] 数字金额大写转换 v2
  19. oracle add_months()函数
  20. 把若干个亚群合并到一起得到subsetdata merge到一起

热门文章

  1. Android禁用wifi实现方法,彻底无限制
  2. free -g cached满了,怎么释放buff/cache的内存占用。
  3. cocos微信小游戏开发-http请求-使用微信云函数-toast-loading-动态加载图片-添加触摸事件-微信分享-label点击事件-背景音乐音效-程序活动状态判断-性能优化
  4. java socket通信的简要举例
  5. 关于Steam 教育的知识整理
  6. STM32CUBE_IIC_读写EEPROM24C64
  7. HACKADEMIC: RTB1
  8. 抖音开放平台用户授权获取用户的粉丝统计和短视频数据
  9. 金融科技大数据产品推荐:享宇金服-智能金融云
  10. QML实现的简单图文编辑器