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. Jewels and Stones

    题目如下 You're given strings J representing the types of stones that are jewels, and S representing the ...

  2. 2018 Wannafly summer camp Day8--连通块计数

    连通块计数 描述 题目描述: 小 A 有一棵长的很奇怪的树,他由 n 条链和 1 个点作为根构成,第 i条链有 ai​ 个点,每一条链的一端都与根结点相连. 现在小 A 想知道,这棵长得奇怪的树有多少 ...

  3. python3爬取全站美眉图片

    爬取网站:https://www.169tp.com/xingganmeinv 该网站美眉图片有数百页,每页24张,共上万张图片,全部爬取下来 import urllib.request import ...

  4. Zabbix——自动发现

    前提条件: Zabbix版本为4.0 固定网段寻找网络设备,并添加组.添加模板.添加proxy. 设置完毕,等待~~ 如果没有问题,将会直接出现在host中.

  5. 关于MySQL自增主键的几点问题(上)

    前段时间遇到一个InnoDB表自增锁导致的问题,最近刚好有一个同行网友也问到自增锁的疑问,所以抽空系统的总结一下,这两个问题下篇会有阐述. 1. 划分三种插入类型 这里区分一下几种插入数据行的类型,便 ...

  6. input 输入的一些限制说明

    input输入框 只能输入 数字可以有小数点 <input class="form_text" id="purchasePrice" name=" ...

  7. ELK的端口以及加入x-pack的密码问题

    ElasticSearch的端口: http://localhost:9200 http://localhost:9200/_plugin/head Kibana的端口: http://localho ...

  8. Zabbix 3.4.11版本 自定义监控项

    一.实验思路过程 创建项目.触发器.图形,验证监控效果: Template OS Linux 模板基本涵盖了所有系统层面的监控,包括了我们最关注的 几项:ping.load.cpu 使用率.memor ...

  9. ACM1003:Max Sum

    Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum ...

  10. go学习笔记-错误处理

    错误处理 通过内置的错误接口提供了非常简单的错误处理机制. error类型是一个接口类型 type error interface { Error() string } 可以在编码中通过实现 erro ...