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. 远程连接Oracle 服务器 解决Oracle查询中文乱码

    Dos方法: 依托于 目录下的文件 使用plsql developer 客户端软件进行连接 需要配置一下: 就是把Dos的客户端配置进来 然后,把服务器端的文件拷贝到你的的机器 并设置TNS_ADMI ...

  2. Ubuntu之C++开发环境的搭建

    初学Linux,今天反复卸载与重装微软商店的Ubuntu好几次,终于解锁了在Ubuntu上搭建C++开发环境的正确姿势, 搭建了一个非常简单的开发环境:简单到什么地步呢?只是简单地配置了一下编辑器,安 ...

  3. js加载等待效果

    demo01: 加载首页的时候,可能会很缓慢,放一张等待图片. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN ...

  4. 帝国CMS如何禁止内容关键字替换ALT和title中的关键词为链接

    很多帝国cms用户喜欢使用关键字替换来实现文章自动内链的方法. 为什么要用关键词替换功能呢?这关系到站内优化,下面直接进入正题. 解决办法:打开e/class/functions.php 查找 '/' ...

  5. 使用ntp协议同步本地时间(C语言)

    使用ntp协议同步本地时间 同步服务器使用的东北大学网络授时服务:ntp.neu.edu.cn更多ntp服务器 http://www.ntp.org.cn/ 源代码来自网络,经本人精简ntp部分,供大 ...

  6. fiddler响应报文的headers属性详解

    fiddler响应报文的headers属性详解 (1)Cache头域 1. Cache-Control 在请求报文已经说过了,用于设置缓存的属性,浏览内容不被缓存. 2. Data 生成消息的具体时间 ...

  7. golang 多维哈希(map,hashmap)实践随笔

    有些场景使用多维哈希来存储数据,时间复杂度恒定,简单粗暴好用.这里记录一下. 如下是三维哈希的简单示意图,建议层数不要太多,否则时间久了,自己写的代码都不认识. 下图是三维哈希在内存的存储形式,has ...

  8. 分布式存储系统Kudu与HBase的简要分析与对比

    本文来自网易云社区 作者:闽涛 背景 Cloudera在2016年发布了新型的分布式存储系统——kudu,kudu目前也是apache下面的开源项目.Hadoop生态圈中的技术繁多,HDFS作为底层数 ...

  9. Luogu P3120 [USACO15FEB]牛跳房子(金)Cow Hopscotch (Gold)

    题目传送门 这是一道典型的记忆化搜索题. f[x][y]表示以x,y为右下角的方案数. code: #include <cstdio> #define mod 1000000007 usi ...

  10. JetBrains Makes its Products Free for Students(JetBrains 对学生免费了)

    只要你有大学有些 后缀是 .edu的  如:@buaa.edu.cn,用你的邮箱注册,就可以免费试用 JetBrains了 下面是详细注册步骤: Hello everyone, If you’re o ...