节点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. windows版本rabbitmq安装及日志level设置

    1.DirectX Repair 安装缺失的C++组件,不安装缺失的组件会造成第二部安装erl文件夹缺少bin文件夹2.安装otp_win64_23.1 1.配置 ERLANG_HOME:地址为Erl ...

  2. YII类的映射表机制

    <?php /** * Created by PhpStorm. * Date: 2016/5/25 * Time: 19:09 * * YII的类的映射表 */ namespace front ...

  3. 日夕如是寒暑不间,基于Python3+Tornado6+APScheduler/Celery打造并发异步动态定时任务轮询服务

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_220 定时任务的典型落地场景在各行业中都很普遍,比如支付系统中,支付过程中因为网络或者其他因素导致出现掉单.卡单的情况,账单变成了 ...

  4. mysql中文乱码--存入mysql里的中文变成问号的解决办法

    今天,服务器里测试的时候,发现存入数据库的中文全部变成问号了! 首先想到这是编码问题:于是乎再次设置数据库的编码为utf8 可是,问题仍然存在: 后来发现,这个问题的根源应该是: 虽然数据库编码是ut ...

  5. Bert不完全手册7. 为Bert注入知识的力量 Baidu-ERNIE & THU-ERNIE & KBert

    借着ACL2022一篇知识增强Tutorial的东风,我们来聊聊如何在预训练模型中融入知识.Tutorial分别针对NLU和NLG方向对一些经典方案进行了分类汇总,感兴趣的可以去细看下.这一章我们只针 ...

  6. Excel 查找函数(一):LOOKUP

    序号 员工姓名 部门 职务 1 苏霞 法务部 法律顾问 2 包志林 财务部 财务总监 3 林娥云 安监部 部长 4 石少卿 质检部 质检员 5 于炳福 生产部 生产部 6 蒋琼志 仓储部 保管员 7 ...

  7. JavaScript(上)

    说说你对作用域链的理解 作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到 window 对象即被终止,作用域链向下访问变量是不被允许的. 简单的说,作 ...

  8. HDU2065 “红色病毒”问题 (指数型母函数经典板题)

    题面 医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色病毒",经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶, ...

  9. 【MySQL】从入门到掌握3-WorkBench

    上期:[MySQL]从入门到掌握2-下载安装 我们安装完MySQL Server的时候,是没有任何界面的. 不过很好,我们有一个工具,MySQL Workbench,他可以简化我们的操作,有点像Jav ...

  10. 区块相隔虽一线,俱在支付同冶熔,Vue3.0+Tornado6前后端分离集成Web3.0之Metamask区块链虚拟三方支付功能

    最近几年区块链技术的使用外延持续扩展,去中心化的节点认证机制可以大幅度改进传统的支付结算模式的经营效率,降低交易者的成本并提高收益.但不能否认的是,区块链技术也存在着极大的风险,所谓身怀利器,杀心自起 ...