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

求开车总行程最短。

就是求一最小生成树,可是对于当中一个点其度不能超过k。

思路:

1. 将park点取出 将剩下的点求出最小生成树  出现i个联通块

2. 再每一个块中选择与park点相邻的最小边

到此park点已经连了i条边

park点最大能够连接k个点

得到Sum值

3. 须要求出i+1-->k 条的Sum值

每次加入一条边在树上形成一个环 然后 删去一条环上的边(权值最大)取Sum=min(Sum,Sum+加入边-删去边)  复杂度O(n^2)

由于第三步复杂度高须要优化第三步

优化:先记录Vi->Vp路径上且不与Vp直接相连的边的权值的Max[ i ]

加入边时 取cost(Vi,Vp)-Max [ i ]最小值 加入(Vi,Vp)边

再枚举ViVp原有的路径上不与Vp相连的边,找到最大权值的边;

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
const int maxn =111+5;
const int maxe = 15000+5;
const int INF = 460002326;
#include <map>
map<string,int>mp;
map<string,int>::iterator it;
int car,n,cost[maxn][maxn],sum,father[maxn];
int best[maxn];
bool vis[maxn];
bool edge[maxn][maxn];
bool use[maxn];
void dfs(int root)//将一个连通块中各个点标记其father
{for(int i=1; i<n; i++){if(vis[i]&&edge[root][i]){father[i]=root;vis[i]=false;dfs(i);}}
}
void prim(int s)
{int Min_i,Min,dis[maxn],num[maxn];memset(vis,false,sizeof(vis));for(int i=0; i<n; i++){dis[i]=cost[i][s];num[i]=s;//此时dis[i]的值来自哪个点}dis[s]=0;vis[s]=use[s]=true;while(true){Min=INF,Min_i=-1;for(int i=0; i<n; i++){if(!use[i]&&!vis[i]&&(Min_i==-1||Min>dis[i])){Min_i=i;Min=dis[i];}}if(Min==INF)    break;sum+=Min;vis[Min_i]=true;use[Min_i]=true;//标记连通块用过的点edge[Min_i][num[Min_i]]=edge[num[Min_i]][Min_i]=true;for(int i=0; i<n; i++){if(!use[i]&&!vis[i]&&dis[i]>cost[i][Min_i]){num[i]=Min_i;dis[i]=cost[i][Min_i];}}}Min=INF;int root=-1;for(int i=0; i<n; i++)//寻找该连通块到Park点的最小距离{if(vis[i]&&cost[0][i]<Min&&i!=0)//在这棵树中{Min=cost[0][i];root=i;}}vis[root]=false;dfs(root);//以root为根father[root]=0;sum+=Min;
}
int Best(int j)//更新当中各个点到park路径上边权值最大的点
{if(father[j]==0)//假设father为0,记为-1return best[j]=-1;if(best[j]!=-1) return best[j];//假设已经存在 。直接返回int tmp=Best(father[j]);if(tmp!=-1)//这说明其父节点不与park相连{if(cost[tmp][father[tmp]]>cost[father[j]][j])best[j]=tmp;else best[j]=j;}else best[j]=j;//其父节点与source相连  将j赋给自己return best[j];
}
void solve()
{int mst=0;memset(father,-1,sizeof(father));memset(use,0,sizeof(use));memset(edge,false,sizeof(edge));use[0]=true;for(int i=0; i<n; i++){if(!use[i])//use用过要标记{prim(i);//除Park外建最小生成树mst++;}}for(int i=mst+1; i<n&&i<=car; i++){memset(best,-1,sizeof(best));for(int j=0; j<n; j++){if(j!=0&&best[j]==-1&&father[j]!=0)Best(j);}int minadd=INF;int ax,bx,change;for(int j=0; j<n; j++){if(cost[0][j]!=INF&&father[j]!=0){ax=best[j];bx=father[ax];if(minadd>cost[0][j]-cost[ax][bx])//cost[0][j]表示加入的边 cost[ax][bx]表示断开的边{                                                       minadd=cost[0][j]-cost[ax][bx];//更新减小的值以及连接的点change=j;}}}if(minadd>=0)   //表示要添加sum值    则已经得到最小的sum值break;sum+=minadd;//更新ax=best[change];bx=father[ax];cost[ax][bx]=cost[bx][ax]=INF;father[change]=0;cost[0][change]=cost[change][0]=INF;}
}
int main()
{int t;// freopen("in.txt","r",stdin);cin>>t;mp.clear();string s1,s2;int val;for(int i=0; i<maxn; i++)for(int j=0; j<maxn; j++)cost[i][j]=INF;n=1,sum=0;mp["Park"]=0;//Park为0;for(int i=0; i<t; i++){cin>>s1>>s2>>val;it=mp.find(s1);//map映射值if(it==mp.end())mp[s1]=n++;it=mp.find(s2);if(it==mp.end())mp[s2]=n++;if(cost[mp[s1]][mp[s2]]>val)//可能会有重边。其实没有。。。。

。 cost[mp[s1]][mp[s2]]=cost[mp[s2]][mp[s1]]=val; } cin>>car; solve(); cout<<"Total miles driven: "<<sum<<endl; return 0; }

转载于:https://www.cnblogs.com/yxwkf/p/5125399.html

poj1639 Picnic Planning 最小度数限制生成树相关推荐

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

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

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

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

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

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

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

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

  5. Poj·Picnic Planning

    初见安~这里是传送门:Poj P1639 Description The Contortion Brothers are a famous set of circus clowns, known wo ...

  6. POJ1629:picnic planning

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

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

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

  8. CF888G XOR-MST 最小异或生成树

    CF888G XOR-MST 链接 CF888G 思路 trie上贪心,先左右两边连边,再用一条边的代价连起左右两颗树.因为内部的边一定比跨两棵树的边权笑,显然是对的. 代码自己瞎yy的.启发式合并 ...

  9. OI每周刷题记录——lrllrl

    看这标题就知道我是模仿的hzwer大佬,远程%%% 大佬的OI经历让蒟蒻我深受感触,为了晚一些AFO本蒟蒻也得加油了 从高二上期第一周开始计数,每个星期天更一次,一直更到我AFO 如果这是我此生最后一 ...

最新文章

  1. 架构模式: 事务日志跟踪
  2. Linux系统弱口令检测和网络端口扫描方法(JR、NMAP)
  3. c3p0配置 initialPoolSize 和minPoolSize 可以设为0吗?设0有坏处吗?
  4. 怎么看台式计算机是几位的,怎么看电脑是32位还是64位?一目了然
  5. linux服务端口加密,linux – 如何通过单个端口处理加密和未加密的http连接
  6. Linux学习(3)Linux文件的基本属性、文件内容查看
  7. 【计算机组成原理】1.计算机系统概述
  8. 外贸出口管理系统亮点及重点
  9. 改纸盒大小_包装纸箱改大小
  10. MyBatis 学习笔记(全)
  11. Jetpack:Room超详细使用踩坑指南!
  12. 火狐浏览器截图整个网页截图 截取整个网页
  13. 虾神段子小剧场:人人都该学点数据分析(1):达五十万的电竞人才缺口?
  14. 编译原理:LL(1)文法 语法分析器(预测分析表法)
  15. ASEMI整流二极管10A10参数,10A10压降,10A10作用
  16. ajax post提交多个参数后台controller @RequestParam方式接收
  17. Explaining Deep Neural Networks
  18. 基于数据结构和C语言实现公交管理系统(含文档和代码)数据结构课程设计
  19. 【共享经济】披着共享经济外衣的租赁经济
  20. html小说阅读页面,html页面布局

热门文章

  1. nvme分区选mbr还是guid_硬盘分区不求人:秒懂MBR和GPT分区表
  2. 风投是如何逆势布局DeFi项目的?
  3. WinRAR的命令行模式与用法介绍
  4. excel模拟运算表
  5. 阿里合伙人制度的意义及法律分析
  6. 2019-2020 ICPC Asia Hong Kong Regional Contest
  7. html 实现自动填表
  8. Gaussdb 存储过程
  9. 兄弟hl3150cdn打印测试页6_兄弟3150CDN彩色激光打印机
  10. 比MySQL快839倍!揭开分析型数据库JCHDB的神秘面纱