poj 1639 Picnic Planning k限制生成树问题
2014-10-14 19:40
369 查看
题意:有一群兄弟去野餐,可以自己开车到目的地,或者开车到A的家里,然后和A一起去目的地。但目的地的停车场不一定容得下,如果每个人都自己开车去的话。所以这对连接到Park的边数有个限制。求他们总路径的最小值。
本体是一道k度限制生成树问题,可以参看资料:
http://wenku.baidu.com/view/70ef0e00eff9aef8941e06db.html
看后结合代码理解这种题目:当时参考了别人的代码
/*
最小k限制最小生成树;
*/
#include<iostream>
#include<cstdio>
#include <cstring>
#include <map>
#include<string>
using namespace std;
#define inf (1<<30)
#define M 30
int pre[M];
int g[M][M];
int link[M][M];
int vist[M];
map<string,int>name;
struct node {
int u, v, len;
node(){}
node(int u, int v, int len):u(u),v(v),len(len){}
}point[M];
int k;
int root;
int ans;
int n, m;
void init(){
int len;
int u, v;
ans = 0;
char s1[20], s2[20];
memset(g, 0x3f, sizeof(g));
memset(vist, 0, sizeof(vist));
memset(link, 0, sizeof(link));
map<string, int >::iterator it1, it2; //map的应用很好的解决了读入问题;
name.clear();
name["Park"] = 0;
n = 1;
for(int i = 0; i < m; i++){
scanf("%s%s%d", s1, s2, &len);
it1 = name.find(s1);
it2 = name.find(s2);
if(it1 != name.end()) u = it1->second;
else {
name[s1] = n;
u = n++;
}
if(it2 != name.end()) v = it2->second;
else {
name[s2] = n;
v = n++;
}
if(g[u][v] > len)
g[u][v] = g[v][u] = len;
}
// for(int i = 0; i < n; i++)
// for(int j= 0; j < n; j++){
//
// printf("%d %d %d\n", i, j, g[i][j]);
// }
scanf("%d", &k);
}
void prime(int u){
int dis[M];
int minn = inf;
int index = -1;
vist[u] = 1;
memset(pre, -1, sizeof(pre));
for(int i = 1; i < n; i++){
dis[i] = g[u][i];
pre[i] = u;
}
// dis[u] = 0;
while(1){
minn = inf;
index = -1;
for(int i = 1; i < n; i++){
if(!vist[i] && dis[i] < minn){
minn = dis[i];
index = i;
}
}
if(index == -1)
break;
link[pre[index]][index] = link[index][pre[index]] = 1;
vist[index] = 1;
ans += dis[index];
if(g[0][root] > g[0][index])
root = index;
for(int i = 1; i < n; i++){
if(!vist[i] && dis[i] > g[index][i]){
dis[i] = g[index][i];
pre[i] = index;
}
}
}
}
void dfs(int cur, int score, int u, int v){ //cur 当前点, score当前点的前驱,存在最长边的两个点。
for(int i = 1; i < n; i++){
if(i != score && link[cur][i]){ //不是还回边或不在最小生成树中的边。
if(score == -1 || g[cur][i] >= g[u][v]){
point[i] = node(cur, i, g[cur][i]);
dfs(i, cur, cur, i);
}else {
point[i] = node(u, v, g[u][v]);
dfs(i, cur, u, v);
}
}
}
}
void work(){
for(int i = 1; i < n; i++){
if(vist[i]) continue;
k--;
root = i;
prime(i);
ans += g[0][root];
link[0][root] = link[root][0] = 1;
dfs(root, -1, -1, -1);
}
while(k--){
int c= 0, index;
for(int i = 1; i < n; i++){
if(link[0][i] || g[0][i] == inf) continue;
if(g[0][i] - point[i].len < c){
c = g[0][i] - point[i].len;
index = i;
}
}
if(c == 0)
break;
if(c < 0){
link[point[index].u][point[index].v] = link[point[index].v][point[index].u] = 0;
link[0][index] = link[index][0] = 1;
ans += c;
dfs(index, -1, -1, -1);
}
}
printf("Total miles driven: %d\n", ans);
}
int main()
{
while(scanf("%d", &m) != EOF){
init();
work();
}
return 0;
}
本体是一道k度限制生成树问题,可以参看资料:
http://wenku.baidu.com/view/70ef0e00eff9aef8941e06db.html
看后结合代码理解这种题目:当时参考了别人的代码
/*
最小k限制最小生成树;
*/
#include<iostream>
#include<cstdio>
#include <cstring>
#include <map>
#include<string>
using namespace std;
#define inf (1<<30)
#define M 30
int pre[M];
int g[M][M];
int link[M][M];
int vist[M];
map<string,int>name;
struct node {
int u, v, len;
node(){}
node(int u, int v, int len):u(u),v(v),len(len){}
}point[M];
int k;
int root;
int ans;
int n, m;
void init(){
int len;
int u, v;
ans = 0;
char s1[20], s2[20];
memset(g, 0x3f, sizeof(g));
memset(vist, 0, sizeof(vist));
memset(link, 0, sizeof(link));
map<string, int >::iterator it1, it2; //map的应用很好的解决了读入问题;
name.clear();
name["Park"] = 0;
n = 1;
for(int i = 0; i < m; i++){
scanf("%s%s%d", s1, s2, &len);
it1 = name.find(s1);
it2 = name.find(s2);
if(it1 != name.end()) u = it1->second;
else {
name[s1] = n;
u = n++;
}
if(it2 != name.end()) v = it2->second;
else {
name[s2] = n;
v = n++;
}
if(g[u][v] > len)
g[u][v] = g[v][u] = len;
}
// for(int i = 0; i < n; i++)
// for(int j= 0; j < n; j++){
//
// printf("%d %d %d\n", i, j, g[i][j]);
// }
scanf("%d", &k);
}
void prime(int u){
int dis[M];
int minn = inf;
int index = -1;
vist[u] = 1;
memset(pre, -1, sizeof(pre));
for(int i = 1; i < n; i++){
dis[i] = g[u][i];
pre[i] = u;
}
// dis[u] = 0;
while(1){
minn = inf;
index = -1;
for(int i = 1; i < n; i++){
if(!vist[i] && dis[i] < minn){
minn = dis[i];
index = i;
}
}
if(index == -1)
break;
link[pre[index]][index] = link[index][pre[index]] = 1;
vist[index] = 1;
ans += dis[index];
if(g[0][root] > g[0][index])
root = index;
for(int i = 1; i < n; i++){
if(!vist[i] && dis[i] > g[index][i]){
dis[i] = g[index][i];
pre[i] = index;
}
}
}
}
void dfs(int cur, int score, int u, int v){ //cur 当前点, score当前点的前驱,存在最长边的两个点。
for(int i = 1; i < n; i++){
if(i != score && link[cur][i]){ //不是还回边或不在最小生成树中的边。
if(score == -1 || g[cur][i] >= g[u][v]){
point[i] = node(cur, i, g[cur][i]);
dfs(i, cur, cur, i);
}else {
point[i] = node(u, v, g[u][v]);
dfs(i, cur, u, v);
}
}
}
}
void work(){
for(int i = 1; i < n; i++){
if(vist[i]) continue;
k--;
root = i;
prime(i);
ans += g[0][root];
link[0][root] = link[root][0] = 1;
dfs(root, -1, -1, -1);
}
while(k--){
int c= 0, index;
for(int i = 1; i < n; i++){
if(link[0][i] || g[0][i] == inf) continue;
if(g[0][i] - point[i].len < c){
c = g[0][i] - point[i].len;
index = i;
}
}
if(c == 0)
break;
if(c < 0){
link[point[index].u][point[index].v] = link[point[index].v][point[index].u] = 0;
link[0][index] = link[index][0] = 1;
ans += c;
dfs(index, -1, -1, -1);
}
}
printf("Total miles driven: %d\n", ans);
}
int main()
{
while(scanf("%d", &m) != EOF){
init();
work();
}
return 0;
}
相关文章推荐
- 【POJ】1639 Picnic Planning 度限制最小生成树
- POJ 1639 Picnic Planning【度限制最小生成树】
- POJ 1639 Picnic Planning(有限制的最小生成树)
- POJ 1639 Picnic Planning(度限制最小生成树)
- poj_1639 Picnic Planning(度限制最小生成树)
- POJ 1639 Picnic Planning【度限制最小生成树】
- POJ 1639 Picnic Planning 【最小度限制生成树】
- poj 1639 Picnic Planning 单度限制的最小生成树
- Picnic Planning poj 1639 k度限制生成树
- POJ1639 Picnic Planning —— 根节点度数有限制的最小生成树
- Picnic Planning POJ - 1639 限制顶点度数的MST
- poj 1639 有限制的最小生成树
- POJ 1639 Picnic Planning (k度限制最小生成树)
- 度限制最小生成树 POJ 1639 贪心+DFS+prim
- POJ 1639 最小度限制生成树
- poj1639 Picnic Planning,K度限制生成树
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
- POJ-1639 Picnic Planning (最小度限制生成树)(模板题)
- poj1639 Picnic Planning,K度限制生成树
- [poj1639]度限制生成树