Description

The Contortion Brothers are a famous set of circus clowns, known worldwide for their incredible ability to cram an unlimited number of themselves into even the smallest vehicle. During the off-season, the brothers like to get together for an Annual Contortionists Meeting at a local park. However, the brothers are not only tight with regard to cramped quarters, but with money as well, so they try to find the way to get everyone to the party which minimizes the number of miles put on everyone's cars (thus saving gas, wear and tear, etc.). To this end they are willing to cram themselves into as few cars as necessary to minimize the total number of miles put on all their cars together. This often results in many brothers driving to one brother's house, leaving all but one car there and piling into the remaining one. There is a constraint at the park, however: the parking lot at the picnic site can only hold a limited number of cars, so that must be factored into the overall miserly calculation. Also, due to an entrance fee to the park, once any brother's car arrives at the park it is there to stay; he will not drop off his passengers and then leave to pick up other brothers. Now for your average circus clan, solving this problem is a challenge, so it is left to you to write a program to solve their milage minimization problem.

Input

Input will consist of one problem instance. The first line will contain a single integer n indicating the number of highway connections between brothers or between brothers and the park. The next n lines will contain one connection per line, of the form name1 name2 dist, where name1 and name2 are either the names of two brothers or the word Park and a brother's name (in either order), and dist is the integer distance between them. These roads will all be 2-way roads, and dist will always be positive.The maximum number of brothers will be 20 and the maximumlength of any name will be 10 characters.Following these n lines will be one final line containing an integer s which specifies the number of cars which can fit in the parking lot of the picnic site. You may assume that there is a path from every brother's house to the park and that a solution exists for each problem instance.

Output

Output should consist of one line of the form 
Total miles driven: xxx 
where xxx is the total number of miles driven by all the brothers' cars.
 
题目大意:有一群人开车到某地,但是某地的停车场又只能停k部车。不过呢,这群人可以先开车到另外一个人的家里,然后搭别人的便车(车没有坐人的上限噢,开挂的民族……)到某地。然后呢,他们又很省钱,希望花的钱最少(也就是车驶过的路径最小,因为开车要油嘛等等),问最短距离是多少。(又不告诉你边数上限,也不告诉你有几个人,慢慢算吧……)
思路:最小生成树。如果一个人开车到了另外一个人的地方,肯定会坐别人的车,省钱嘛,所以很容易能看出总路径就是最小生成树,而对某个点的度数有所限制,则对最小度限制生成树稍作修改即可(这题可不一定要停满别人的停车场啊……)。更详细的可以去看2004年 汪汀 的论文《最小生成树问题的拓展》
 
PS:V好小啊只有20是要闹哪样啊……
PS:没事翻博客的时候发现这代码有BUG,虽然AC了,不过我懒得改了就这样吧……
 
代码写得有点挫……
 #include <cstring>
#include <string>
#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std; const int MAXN = ;
const int INF = 0x7f7f7f7f; struct Node {
int u, v, c, use;
Node() {}
Node(int uu, int vv, int cc): u(uu), v(vv), c(cc), use(false) {}
bool operator < (const Node &rhs) const {
return c < rhs.c;
}
}; map<string, int> mymap;
string s1, s2;
int n, m, k, ecnt, ans, cnt;
Node *p;
int fa[MAXN], head[MAXN], *next;
int mat[MAXN][MAXN]; void init() {
ecnt = n = ;
p = new Node[ * m + ];
next = new int[ * m + ];
mymap.clear();
mymap["Park"] = n++;
memset(mat, , sizeof(mat));
} int get_set(int x) {
return fa[x] == x ? x : get_set(fa[x]);
} void add_edge(int u, int v, int c) {
p[ecnt++] = Node(u, v, c);
p[ecnt++] = Node(v, u, c);
if(mat[u][v] == || c < mat[u][v])
mat[u][v] = mat[v][u] = c;
} void build_link() {
memset(head, -, sizeof(head));
for(int i = ecnt - ; i >= ; --i) {
next[i] = head[p[i].u];
head[p[i].u] = i;
}
} void kruskal_del0() {
ans = cnt = ;
for(int i = ; i < ecnt; ++i) {
if(p[i].u == || p[i].v == ) continue;
int x = get_set(p[i].u), y = get_set(p[i].v);
if(x == y) continue;
fa[x] = y;
p[i].use = p[i ^ ].use = true;
ans += p[i].c;
++cnt;
}
m = n - - cnt;
build_link();
for(int i = head[]; i != -; i = next[i]) {
if(p[i].u && p[i].v) continue;
int x = get_set(p[i].u), y = get_set(p[i].v);
if(x == y) continue;
fa[x] = fa[y] = ;
p[i].use = p[i ^ ].use = true;
ans += p[i].c;
if(++cnt == n - ) break;
}
} void dfs(int x) {
for(int i = head[x]; i != -; i = next[i]) {
if(p[i].use) {
fa[p[i].v] = x;
p[i].use = p[i ^ ].use = false;
dfs(p[i].v);
}
}
} int best[MAXN]; int get_best(int x) {
if(fa[x] == ) return -;
if(best[x] != -) return best[x];
return best[x] = max(mat[x][fa[x]], get_best(fa[x]));
} void exchange_edge() {
while(m++ < k) {
memset(best, -, sizeof(best));
for(int i = ; i < n; ++i) get_best(i);
int a = INF, y = ;
for(int i = head[]; i != -; i = next[i]) {
if(best[p[i].v] != - && a > p[i].c - best[p[i].v]) {
a = p[i].c - best[p[i].v];
y = p[i].v;
}
}
if(a >= ) return ;
ans += a; fa[y] = ;
}
} int main() {
int c;
while(scanf("%d", &m) != EOF) {
init();
while(m--) {
cin>>s1>>s2>>c;
if(mymap.find(s1) == mymap.end()) mymap[s1] = n++;
if(mymap.find(s2) == mymap.end()) mymap[s2] = n++;
add_edge(mymap[s1], mymap[s2], c);
}
scanf("%d", &k);
for(int i = ; i < n; ++i) fa[i] = i;
sort(p, p + ecnt);
kruskal_del0();
dfs();
exchange_edge();
printf("Total miles driven: %d\n", ans);
delete [] p;
delete [] next;
}
}

POJ 1639 Picnic Planning(最小度限制生成树)的更多相关文章

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

    题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...

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

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

  3. [POJ 1639] Picnic Planning

    [题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...

  4. poj 1639 Picnic Planning 度限制mst

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

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

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

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

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

  7. POJ1639 - Picnic Planning

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

  8. K度限制MST poj 1639

    /* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...

  9. luogu P5633 最小度限制生成树 wqs二分

    LINK:最小度限制生成树 还是WQS二分的模板题 不过相当于我WQS二分的复习题. 对于求出强制k个的答案 dp能做不过复杂度太高了. 世界上定义F(x)表示选出x个的答案 画成图像 其实形成了一个 ...

随机推荐

  1. JQuery的焦点事件focus() 与按键事件keydown() 及js判断当前页面是否为顶级页面 子页面刷新将顶级页面刷新 window.top.location

    相关代码如下,使用看注解 <script type="text/javascript"> if(window.self != window.top){ window.t ...

  2. Resharp常用设置收集整理

    F12跳转的问题:

  3. 集群、RAC和MAA

    集群:是一种由两台或多台节点机构成的松散耦合的计算节点集合,这个集合在整个网络中表现为单一的系统,并通过单一接口进行使用和管理.给用户提供网络服务或应用程序的单一视图.大多数模式下,集群中所有计算机都 ...

  4. Debian中CodeIgniter+nginx+MariaDB+phpMyAdmin配置

    本文不讲述软件安装过程,记述本人在Debia中配置CodeIgniter时遇到的问题及解决方法,希望能够为有需要的人提供帮助. 一.Debian版本及所需的软件 Debian 9.8 stretch ...

  5. spark成长之路(1)spark究竟是什么?

    今年6月毕业,来到公司前前后后各种事情折腾下来,8月中旬才入职.本以为终于可以静下心来研究技术了,但是又把我分配到了一个几乎不做技术的解决方案部门,导致现在写代码的时间都几乎没有了,所以只能在每天下班 ...

  6. Java使用zxing生成解读QRcode二维码

    1.maven的pom配置jar包,如果不实用maven请手动下载jar包 <dependency> <groupId>com.google.zxing</groupId ...

  7. 【NXP开发板应用—智能插排】1.如何使用scp传输文件

    首先感谢深圳市米尔科技有限公司举办的这次活动并予以本人参加这次活动的机会,以往接触过嵌入式,但那都是皮毛,最多刷个系统之类的,可以说对于嵌入式系统开发这件事情是相当非常陌生的,这次活动为我提供了一个非 ...

  8. python学习笔记:第12天 列表推导式和生成器

    目录 1. 迭代器 2. 推导式 1. 迭代器 什么是生成器呢,其实生成器的本质就是迭代器:在python中有3中方式来获取生成器(这里主要介绍前面2种) 通过生成器函数获取 通过各种推导式来实现生成 ...

  9. python3 练习题100例 (五)

    题目五:输入三个整数x,y,z,请把这三个数由小到大输出. #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 题目五: ...

  10. 成都Uber优步司机奖励政策(4月8日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...