节点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. 一个小 Trick

    平方变两次 一个状态 \(S\) 有一个贡献,所有状态 \(S\) 组成集合 \(U\) . 然后我们要统计下面这个东西 \[ans=\sum_{S\in U}f^2(S) \] 然后我们就可以看作是 ...

  2. 我又造了个轮子:GrpcGateway

    我个人对GRPC是比较感兴趣的,最近在玩通过前端调用GRPC.通过前端调用GRPC业界有两种方式:GRPC Web和GRPC JSON转码. GRPC Web 通过JS或者Blazor WASM调用G ...

  3. Vue3系列2--项目目录介绍及运行项目

    1 Vite项目目录 用Vscode打开创建的项目,看到下面的目录结构: 通过运行  npm install 初始化项目后生成两个初始化文件:node_modules和 package-lock.js ...

  4. 小试牛刀:Linux中部署RabbitMQ

    一.下载地址 本人采用的是 RabbitMQ 3.8.20+ Erlang 23.3.4.16 1.Erlang下载:https://github.com/erlang/otp/releases 2. ...

  5. 无法访问mybatis.dto.StudengInVO-使用maven编译报错-2022新项目

    一.问题由来 最近一次拉代码后,合并代码然后进行编译时出现一个问题,使用maven在进行编译的时候报一个错,无法访问mybatis.dto.StudengInVO. 突然出现这个错误让自己感觉很奇怪, ...

  6. CF360E Levko and Game(贪心)

    这题贪心停水的,找\(dis1<=dis2\)的点往歇斯底里地砍,砍到没法砍就是. 写博客是为了记录下遇到的神奇bug #include <iostream> #include &l ...

  7. Redis 01 概述

    参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 简介 NoSQ ...

  8. Shiro反序列化利用

    Shiro反序列化利用 前言:hvv单位这个漏洞挺多的,之前没专门研究打法,特有此篇文章. Shiro rememberMe反序列化漏洞(Shiro-550) 漏洞原理 Apache Shiro框架提 ...

  9. 应用性能监控:SkyWalking

    目录 SkyWalking 简介 SkyWalking 搭建 平台后端(Backend) 平台前端(UI) Java Agent(Java 应用监控) Java Agent 下载 Java 演练项目 ...

  10. 记录一次数据库CPU被打满的排查过程

    1 前言 近期随着数据量的增长,数据库CPU使用率100%报警频繁起来.第一个想到的就是慢Sql,我们对未合理运用索引的表加入索引后,问题依然没有得到解决,深入排查时,发现在 order by id ...