节点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 (限制入度最小生成树)的更多相关文章

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

    解法参考的论文:https://wenku.baidu.com/view/8abefb175f0e7cd1842536aa.html 觉得网上的代码好像都是用邻接矩阵来实现的,觉得可能数据量大了会比较 ...

  2. POJ1639 - Picnic Planning

    原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...

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

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

  4. poj1639 Picnic Planning,K度限制生成树

    题意: 矮人虽小却喜欢乘坐巨大的轿车,车大到能够装下不管多少矮人.某天,N(N≤20)个矮人打算到野外聚餐.为了集中到聚餐地点,矮人A 要么开车到矮人B 家中,留下自己的轿车在矮人B 家,然后乘坐B ...

  5. UVA1537 Picnic Planning(思维+最小生成树)

    将1号点从图中去掉过后,图会形成几个连通块,那么我们首先可以在这些连通块内部求最小生成树. 假设有\(tot\)个连通块,那么我们会从1号点至少选\(tot\)个出边,使得图连通.这时我们贪心地选择最 ...

  6. poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10742   Accepted: 3885 ...

  7. POJ 1639 Picnic Planning 最小k度生成树

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions:11615   Accepted: 4172 D ...

  8. 【POJ 1639】 Picnic Planning (最小k度限制生成树)

    [题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...

  9. poj 1639 Picnic Planning 度限制mst

    https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...

随机推荐

  1. gitlab+jenkins学习笔记

    一.部署gitlab gitlab部署我采用的是docker的方式,这种方式的优势是方便:之前部署过非docker的gitlab,需要配置安装许多东西,太麻烦,还是docker部署方便,从官网pull ...

  2. Bika LIMS 开源LIMS集—— SENAITE的使用(用户、角色、部门)

    设置 添加实验室人员,系统用户 因为创建实验室时必须选择实验室经理/主任/负责人,因此需要先创建实验室经理人员. 创建人员时输入人员姓名,可上传签名图片. 创建实验室部门 输入实验室名称.代码,选择实 ...

  3. Odoo14 一些好用的开源的模块

    # odoo14中一些好用的开源的模块 1.intero_reload_form 刷新按钮(页面数据刷新,而不是按F5刷新整个页面) 2.ms_magic_button 弹框下拉选项 3.sessio ...

  4. Web优化躬行记(6)——优化闭环实践

    在遇到一个页面性能问题时,我理解的优化闭环是:分析.策略.验证和沉淀. 分析需要有分析数据,因此得有一个性能监控管理. 策略就是制订针对性的优化方案,解决当前遇到的问题. 验证的对象上述策略,判断方案 ...

  5. mui 登录之后tab切换页面会失灵

    我的app做完刚进去的时候底部导航栏的tab切换是正常的,但是退出之后重新登录,我在首页用reload进行了刷新,之后就引发了一些问题,tab切换有时候会失灵,登录转态的改变不成功.原来是reload ...

  6. Spring核心思想Ioc和Aop (面试)

    Spring核心思想Ioc和Aop (面试) 注意: Ioc和Aop并不是Spring提出的,在Spring之前就已经存在,Spring只是在技术层面给这两个思想做了非常好的实现. 1 Ioc 1.1 ...

  7. C++ UAC 提权 以一个管理员身份运行程序

    这里是我编译的和一个测试Demo:http://pan.baidu.com/s/1qWNgC6C 大家如果看我下边的不是很清楚,可以下载这个具体工程: 群:103197177 C++进阶讨论:欢迎喜欢 ...

  8. linux 3.10 一个扇区异常可能引发的hung

    最近遇到一例3.10内核的crash: [ 4109.682163] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" d ...

  9. mac怎么清理DNS缓存

    可以通过Mac系统启动台功能,在其他页面打开终端进行操作即可. 1.打开终端 2.进入终端界面,输入sudo killall -HUP mDNSResponder命令执行即可.

  10. HDU 6467 简单数学题 (组合数学推导)

    题意 题解 Step 1 把原式进行了最基本的变换,把 i 移到右边,并先枚举 j ,这里 i 从 0 开始枚举,并不影响答案,因为 C(j,0) 乘 0 后没有影响,但是这样方便后面的推导 Step ...