节点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. canal-1.1.5实时同步MySQL数据到Elasticsearch

    一.环境准备 1.jkd 8+ 2.mysql 5.7+ 3.Elasticsearch 7+ 4.kibana 7+ 5.canal.adapter 1.1.5 二.部署 一.创建数据库CanalD ...

  2. 使用Hexo建立一个轻量、简易、高逼格的博客

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_93 在之前的一篇文章中,介绍了如何使用Hugo在三分钟之内建立一个简单的个人博客系统,它是基于go lang的,其实,市面上还有一 ...

  3. 使用Docker-compose来封装celery4.1+rabbitmq3.7服务,实现微服务架构

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_115 大家都知道,Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统,在之前的一篇文章中:python3.7+Torn ...

  4. 浩若烟海事半功倍|利用Docker容器技术构建自动化分布式web测试集群Selenium Grid

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_195 "世界上有那么多城市,城市里有那么多的酒馆,可她,却偏偏走进了我的-",这是电影<卡萨布拉卡> ...

  5. 抖音web端 s_v_web_id 参数生成分析与实现

    本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! 抖音web端 s_v_web_id 参数 ...

  6. HCIA-Datacom 3.3 实验三:以太网链路聚合实验

    实验介绍 随着网络规模不断扩大,用户对骨干链路的带宽和可靠性提出越来越高的要求.在传统技术中,常用更换高速率的接口板或更换支持高速率接口板的设备的方式来增加带宽,但这种方案需要付出高额的费用,而且不够 ...

  7. Dart 异步编程(一):初步认识

    由于 Dart 是单线程编程语言,对于进行网络请求和I/O操作,线程将发生阻塞,严重影响依赖于此任务的下一步操作. 通常,在一个阻塞任务之后还有许许多多的任务等待被执行.下一步任务需要上一步任务的结果 ...

  8. 【python】pandas 索引操作

    选择.修改数据(单层索引) 推荐使用.at..iat..loc..iloc 操作 句法 结果 备注 选择列 df[col] Series 基于列名(列的标签),返回Series 用标签选择行 df.l ...

  9. 【Java】学习路径53-InetAdress获取服务器ip

    InetAdress如何使用? import java.net.*; public class InetAdress { public static void main(String[] args) ...

  10. 【java】学习路线15-接口interface、匿名内部类、接口继承

    class Learn03{    public static void main(String[] aa){        A b = new B(); //接口也可以用多态        b.me ...