POJ1639 - Picnic Planning
Description
给出一张n(n≤20)个点的无向边权图并钦定点P,求使得点P的度不超过k的最小生成树。
Solution
首先无视掉与P相连的所有边,原图会变成若干互不连通的t个块。对每个块分别求MST,再从每个块向P连一条最小的边,这样就得到了一个t度最小生成树。不存在度数比t小的生成树了,因为这t个部分只能通过P来连通。这个比较容易理解。
然后考虑如何从t度MST转移为t+1度MST。我们可以尝试加入一条与P相连的边,图中会出现一个环,从环上再删掉一条最大的边就可以得到一棵t+1度生成树。枚举所有与P相连且不在当前的生成树上的边,最小化总权值就好啦。每次转移可以通过BFS找出路径(P,v)上的最大边是哪条。
时间复杂度O(mlogm+kn)。
Code
//Picnic Planning
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
map<string,int> p;
int const N=30;
int const INF=0x3F3F3F3F;
int n,m,rt;
//图的存储
int e[N][N],cnt;
struct edge{int u,v,c; edge(int u1=0,int v1=0,int c1=0){u=u1,v=v1,c=c1;};} ed[N*N],mx[N];
void edAdd(int u,int v,int c)
{
e[u][v]=e[v][u]=min(e[u][v],c);
if(u!=rt&&v!=rt) ed[++cnt]=edge(u,v,c);
}
//划分块相关
int clCnt,f[N];
void extend(int u)
{
for(int v=1;v<=n;v++)
if(e[u][v]<INF&&!f[v]) f[v]=f[u],extend(v);
}
//生成树相关
int sum; bool tr[N][N];
void trSet(int u,int v,bool opt) {tr[u][v]=tr[v][u]=opt; sum+=(opt?1:-1)*e[u][v];}
bool cmpC(edge x,edge y) {return x.c<y.c;}
int fa[N];
int find(int u) {return fa[u]==u?u:fa[u]=find(fa[u]);}
void Kruskal()
{
sort(ed+1,ed+cnt+1,cmpC);
for(int u=1;u<=n;u++) fa[u]=u;
for(int i=1;i<=cnt;i++)
{
int u=ed[i].u,v=ed[i].v;
if(find(u)==find(v)) continue;
fa[find(v)]=find(u); trSet(u,v,true);
}
}
//生成树转移相关
int toRt[N];
int q[N],op,cl;
void bfs()
{
op=cl=0; memset(mx,0,sizeof mx);
q[++cl]=rt; mx[rt].c=-1;
while(op<cl)
{
int u=q[++op];
for(int v=1;v<=n;v++)
{
if(!tr[u][v]||mx[v].c) continue;
q[++cl]=v; mx[v]=e[u][v]>mx[u].c?edge(u,v,e[u][v]):mx[u];
}
}
}
int main()
{
scanf("%d",&m);
n=0; rt=0; memset(e,0x3F,sizeof e);
for(int i=1;i<=m;i++)
{
string s1,s2; int c;
cin>>s1; cin>>s2; scanf("%d",&c);
if(!p[s1]) p[s1]=++n; if(!p[s2]) p[s2]=++n;
if(s1=="Park") rt=p[s1]; if(s2=="Park") rt=p[s2];
edAdd(p[s1],p[s2],c);
}
int k; scanf("%d",&k);
//划分块
f[rt]=n+1; clCnt=0;
for(int i=1;i<=n;i++) if(f[i]==0) f[i]=++clCnt,extend(i);
//建立clCnt度MST
sum=0; Kruskal();
for(int v=1;v<=n;v++) if(e[rt][v]<e[rt][toRt[f[v]]]) toRt[f[v]]=v;
for(int i=1;i<=clCnt;i++) trSet(rt,toRt[i],true);
//由t-1度MST转化为t度MST
for(int t=clCnt+1;t<=k;t++)
{
int v0=0,dlt=INF; bfs();
for(int v=1;v<=n;v++)
if(!tr[rt][v]&&e[rt][v]<INF)
if(e[rt][v]-mx[v].c<dlt) dlt=e[rt][v]-mx[v].c,v0=v;
if(dlt>=0) break;
trSet(mx[v0].u,mx[v0].v,false);
trSet(rt,v0,true);
}
printf("Total miles driven: %d",sum);
return 0;
}
P.S.
又是坑爹的读入…还要注意细节
POJ1639 - Picnic Planning的更多相关文章
- poj1639 Picnic Planning 最小度数限制生成树
题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...
- poj1639 Picnic Planning,K度限制生成树
题意: 矮人虽小却喜欢乘坐巨大的轿车,车大到能够装下不管多少矮人.某天,N(N≤20)个矮人打算到野外聚餐.为了集中到聚餐地点,矮人A 要么开车到矮人B 家中,留下自己的轿车在矮人B 家,然后乘坐B ...
- POJ-1639 Picnic Planning 度数限制最小生成树
解法参考的论文:https://wenku.baidu.com/view/8abefb175f0e7cd1842536aa.html 觉得网上的代码好像都是用邻接矩阵来实现的,觉得可能数据量大了会比较 ...
- POJ1639 Picnic Planning (限制入度最小生成树)
节点1是有度数限制的,把节点1去掉,就会形成若干个连通块,在每个连通块内部求最小生成树(prim算法实现),并求出每个连通块与1相连的最短的边,这样形成了初始状态的生成树. 假设(1,x)这条边没在生 ...
- 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条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...
- Picnic Planning POJ - 1639(最小k度生成树)
The Contortion Brothers are a famous set of circus clowns, known worldwide for their incredible abil ...
随机推荐
- Myeclipse 10安装与破解
首先下载Myeclipse 10的压缩包,我这里以10.7版本为例.下载路径分享 链接:https://pan.baidu.com/s/1nxf19S9 密码:rqw4 下载好后解压,解压后进行安装. ...
- 计算器(Ext)
<html> <head> <title>计算器</title> <meta charset="UTF-8"> < ...
- css 块状元素与行内元素(内联元素)的理解
块状元素: 它一般是其他元素的容器元素,可以容纳块状元素和行内元素,它默认是不会和其他元素同一行的,即相当于两个块状元素写一起是垂直布局的.最常用的是div和p 行内元素: 行内元素又称内联元素,它只 ...
- gd库的安装
gd库简介 主要用途编辑 在网站上GD库通常用来生成缩略图,或者用来对图片加水印,或者用来生成汉字验证码,或者对网站数据生成报表等.在PHP处理图像,可使用GD库,而GD库开始时是支持GIF的,但由于 ...
- Oracle Rac创建表空间及用户
1. 创建表空间: BEGIN DECLARE cnt integer := 0; BEGIN SELECT 1 INTO cnt FROM dual WHERE exists(SELECT * FR ...
- 已知有两个水杯,一个11L一个7L,水可以任意使用,求怎么得到2L 的详细解法
问题:有两个水杯,一个是11L一个是7L,水可以随便用,怎么得到2L 1.了解问题的本质 问题中给出了两个杯子,只有这两个杯子有量度,所以只能让杯中的水满进满出才能确定杯子中最后有多少水. 现在问题要 ...
- 使用py2exe发布windows平台Python
一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具,这样,你就可以不用装python而在windows系统上运行这个可执行程序.py2ex ...
- vue项目实战总结
马上过年了,最近工作不太忙,再加上本人最近比较懒,毫无斗志,不愿学习新东西,或许是要过年的缘故(感觉像是在找接口). 就把前一段时间做过的vue项目,进行一次完整的总结. 这次算是详细总结,会从项目的 ...
- 网络搬砖是件苦力活 CMS推荐GHOS博客程序
搬砖不是技术活,而是苦力(bi)活,富有技术含量的苦力活说不定就是一门可以持续的生意. 我们不生产内容,我们只是互联网的内容搬运工,这是大部分不具备原创能力个人站长的心声.虽然原创能力不够,但是服务目 ...
- OI常用读入方式效率测试
我来填坑了. 这次我用自己写的测试读入的程序来分别测试cin(不关闭流同步),scanf和读入优化的效率差别. 我们分别对三个阶段的数据量n进行测试,通过时间比对来观察性能的差异. n = 102 ...