POJ1639 Picnic Planning (限制入度最小生成树)
节点1是有度数限制的,把节点1去掉,就会形成若干个连通块,在每个连通块内部求最小生成树(prim算法实现),并求出每个连通块与1相连的最短的边,这样形成了初始状态的生成树。
假设(1,x)这条边没在生成树中,如果在生成树中从1到x的路径中的最大边权大于(1,x),考虑加上(1,x),去掉这条最大边权的边,答案就更加优秀了,若干次重复这样的操作,直到达到度数限制,就可以得到最优解。
记录最大边权的思路基于DP,回溯打标记。
完成一次拓展后,加入了(1,x)这条边,修改x的f[ ],fx[ ],fy[ ],给1打上标记,从x开始DP,因为只是修改了x所在的连通块,没有必要再从1遍历一次。(可以画图理解一下)。
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n,m,s,deg,ans;
4 int a[32][32],d[32],conn[32];
5 bool v[32],c[32];
6 int tree[32][32];
7 int ver[32],p;
8 int f[32],fx[32],fy[32];//1-x的路径最大边权是f[x],两个端点是fx[x],fy[x]
9
10 void read(){
11 map<string,int> h;
12 cin>>m;
13 h["Park"]=1;n=1;
14 memset(a,0x3f,sizeof(a));
15 for(int i=1;i<=m;i++){
16 int x,y,z;
17 char sx[12],sy[12];
18 scanf("%s%s%d",sx,sy,&z);
19 if(!h[sx]) h[sx]=++n;
20 if(!h[sy]) h[sy]=++n;
21 x=h[sx],y=h[sy];
22 a[x][y]=min(a[x][y],z);
23 a[y][x]=min(a[y][x],z);
24 }
25 cin>>s;
26 }
27
28 void prim(int root){
29 d[root]=0;
30 for(int i=1;i<=p;i++){
31 int x=0;
32 for(int j=1;j<=p;j++)
33 if(!v[ver[j]]&&(x==0||d[ver[j]]<d[x])) x=ver[j];
34 v[x]=true;
35 for(int j=1;j<=p;j++){
36 int y=ver[j];
37 if(!v[y]&&d[y]>a[x][y])
38 d[y]=a[x][y],conn[y]=x;
39 }
40 }//prim算法模板
41 int closest=root;
42 for(int i=1;i<=p;i++){
43 int x=ver[i];
44 if(x==root) continue;
45 ans+=d[x];
46 tree[conn[x]][x]=tree[x][conn[x]]=d[x];
47 if(a[1][x]<a[1][closest]) closest=x;//记录连通块中和1相连最短的边
48 }
49 deg++;
50 ans+=a[1][closest];
51 tree[1][closest]=tree[closest][1]=a[1][closest];
52 }
53
54 void dfs(int x){
55 ver[++p]=x;
56 c[x]=true;
57 for(int y=2;y<=n;y++)
58 if(a[x][y]!=0x3f3f3f3f&&!c[y]) dfs(y);
59 }
60
61 void prim_for_all_comp(){
62 memset(d,0x3f,sizeof(d));
63 memset(v,0,sizeof(v));
64 memset(tree,0x3f,sizeof(tree));
65 c[1]=true;
66 for(int i=2;i<=n;i++){
67 if(!c[i]){
68 p=0;
69 dfs(i);
70 prim(i);
71 }
72 }
73 }
74
75 void dp(int x){
76 v[x]=true;
77 for(int y=2;y<=n;y++){
78 if(tree[x][y]!=0x3f3f3f3f&&!v[y]){
79 if(f[x]>tree[x][y]){
80 f[y]=f[x];
81 fx[y]=fx[x],fy[y]=fy[x];
82 }else{
83 f[y]=tree[x][y];
84 fx[y]=x,fy[y]=y;
85 }
86 dp(y);
87 }
88 }
89 v[x]=false;//回溯
90 }
91
92 bool solve(){
93 int min_val=1<<30,mini;
94 for(int i=2;i<=n;i++){//枚举从1出发的非树边(1,i),看加哪一条
95 if(tree[1][i]!=0x3f3f3f3f||a[1][i]==0x3f3f3f3f) continue;
96 //加入非树边(1,i),删去树边(fx[i],fy[i])
97 if(a[1][i]-tree[fx[i]][fy[i]]<min_val){
98 min_val=a[1][i]-tree[fx[i]][fy[i]];
99 mini=i;
100 }
101 }
102 if(min_val>=0) return false;
103 ans+=min_val;
104 tree[1][mini]=tree[mini][1]=a[1][mini];
105 tree[fx[mini]][fy[mini]]=tree[fy[mini]][fx[mini]]=0x3f3f3f3f;//删去原边,增加新边
106 f[mini]=a[1][mini];
107 fx[mini]=1,fy[mini]=mini;
108 v[1]=true;
109 dp(mini);//重新计算以mini为根的子树的dp状态
110 return true;
111 }
112
113 int main(){
114 read();
115 prim_for_all_comp();
116 memset(v,0,sizeof(v));
117 dp(1);
118 while(deg<s){
119 if(!solve()) break;
120 deg++;
121 }
122 printf("Total miles driven: ");
123 cout<<ans<<endl;
124 }
POJ1639 Picnic Planning (限制入度最小生成树)的更多相关文章
- POJ-1639 Picnic Planning 度数限制最小生成树
解法参考的论文:https://wenku.baidu.com/view/8abefb175f0e7cd1842536aa.html 觉得网上的代码好像都是用邻接矩阵来实现的,觉得可能数据量大了会比较 ...
- POJ1639 - Picnic Planning
原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...
- poj1639 Picnic Planning 最小度数限制生成树
题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...
- poj1639 Picnic Planning,K度限制生成树
题意: 矮人虽小却喜欢乘坐巨大的轿车,车大到能够装下不管多少矮人.某天,N(N≤20)个矮人打算到野外聚餐.为了集中到聚餐地点,矮人A 要么开车到矮人B 家中,留下自己的轿车在矮人B 家,然后乘坐B ...
- UVA1537 Picnic Planning(思维+最小生成树)
将1号点从图中去掉过后,图会形成几个连通块,那么我们首先可以在这些连通块内部求最小生成树. 假设有\(tot\)个连通块,那么我们会从1号点至少选\(tot\)个出边,使得图连通.这时我们贪心地选择最 ...
- poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 10742 Accepted: 3885 ...
- POJ 1639 Picnic Planning 最小k度生成树
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions:11615 Accepted: 4172 D ...
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
[题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...
- poj 1639 Picnic Planning 度限制mst
https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...
随机推荐
- CF1593D2 Half of Same
题目大意: 给定一个包含 \(n\)(\(n\) 是偶数)个整数的数列 \(a_1,a_2,\ldots,a_n\). 考虑一个可能的正整数 \(k\),在每次操作中,你可以选定一个 \(i\),并将 ...
- HtmlAgilityPack中使用xpath获取属性值
HtmlAgilityPack介绍 HtmlAgilityPack是一个专门用来解析Html的库,它可以使用xml的方式来解析html. 有人说了,html本身不就是xml?是的,html就是xml, ...
- electron-vue打包出现问题汇总
打包过程中出现下载status code 404 1.可能是网络不好,导致相关electron包无法正常下载,也有可能是需要挂代理 2.可能是编译过程的链接出现错误,一般为网址中缺少或多了一个v,建议 ...
- python3.7爬虫:使用Selenium带Cookie登录并且模拟进行表单上传文件
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_142 前文再续,书接上一回,之前一篇文章我们尝试用百度api智能识别在线验证码进行模拟登录:Python3.7爬虫:实时api(百 ...
- spring实体类(POJO)参数的赋值(form表单)原理
10.实体类(POJO)参数的赋值(form表单)原理 10.1.原理解析 测试用例 准备好两个实体类 public class Person { private String name; priva ...
- 分享俩个js数组比较少用的方法join与from
1:array.join 用于将数组中的所有元素转化为字符串 例: var arr = ["one", "two", "four"]; va ...
- Redis 02 数据库
参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 Redis 默 ...
- JDK数组阻塞队列源码深入剖析
JDK数组阻塞队列源码深入剖析 前言 在前面一篇文章从零开始自己动手写阻塞队列当中我们仔细介绍了阻塞队列提供给我们的功能,以及他的实现原理,并且基于谈到的内容我们自己实现了一个低配版的数组阻塞队列.在 ...
- SQL SERVER数据库服务器CPU不能全部利用原因分析
背景 客户凌晨把HIS数据库迁移到配置更高的新服务器,上午业务高峰时应用非常缓慢,严重影响到业务运行. 1.现象 通过SQL专家云实时可视化界面看到大量的绿点,绿点表示会话在等待某项资源,绿点越大 ...
- ASP.NET Core 6框架揭秘实例演示[33]:异常处理高阶用法
NuGet包"Microsoft.AspNetCore.Diagnostics"中提供了几个与异常处理相关的中间件,我们可以利用它们将原生的或者定制的错误信息作为响应内容发送给客户 ...