POJ 1639 Picnic Planning 最小k度生成树
| Time Limit: 5000MS | Memory Limit: 10000K | |
| Total Submissions:11615 | Accepted: 4172 |
Description
Input
Output
Total miles driven: xxx
where xxx is the total number of miles driven by all the brothers' cars.
Sample Input
10
Alphonzo Bernardo 32
Alphonzo Park 57
Alphonzo Eduardo 43
Bernardo Park 19
Bernardo Clemenzi 82
Clemenzi Park 65
Clemenzi Herb 90
Clemenzi Eduardo 109
Park Herb 24
Herb Eduardo 79
3
Sample Output
Total miles driven: 183 思路
一开始在网上搜索题解,照着他们的算法写,写完了才发现,他们有最重要的一步没有讲,幸好此时峰巨告诉了我算法的全过程,orz orz orz。 算法:
1.无视Park及其它的边,建立最小生成树(森林)。
2.选择park到每个树的最短边,与树相连。
3.此时,park到每棵树还剩了一些边,枚举他们,每一条边加进去都会有一个环,删去环内的最大边。枚举的时候不要真实操作(或者操作后还原),而是记录他们的值,选择最大的,再进行删边操作。
4.重复第三步(k-第一步最小生成树的数目)次 博主水平不高,如需帮助,请在下方留言
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int inf = ;
int mp[][],pp;
int dis[],disx[],n,k,kk;
int book[],flag[][];
char name[][];
int e1,e2,f[];
bool vis[];
int fo[];
struct node
{
int pio;
int wei;
int ex1,ex2;
}getr[],exa; int prim(int k)
{
dis[k]=;
int ans=; while(true){
int t=;
for(int i=;i<=n;i++){
if(!book[i]&&dis[i]<dis[t]){
t=i;
}
}
if(t==){break;}
ans+=dis[t];book[t]=k;flag[disx[t]][t]=flag[t][disx[t]]=true;
for(int i=;i<=n;i++){
if(!book[i]&&dis[i]>mp[t][i]){
dis[i]=mp[t][i];
disx[i]=t;
}
} }
return ans;
} void init()
{
for(int i=;i<=;i++){
for(int j=;j<=;j++){
mp[i][j]=inf;
}
}
for(int i=;i<=;i++){
dis[i]=inf;
}
} void scan()
{
int s,x,y;
scanf("%d",&n);
char a[],b[];
int t=;
init();
for(int i=;i<=n;i++){
scanf("%s%s%d",a,b,&s);
x=y=-;
for(int j=;j<=t;j++){
if(!strcmp(name[j],a)){x=j;}
if(!strcmp(name[j],b)){y=j;}
}
if(x==-){x=++t;strcpy(name[t],a);}
if(y==-){y=++t;strcpy(name[t],b);}
mp[x][y]=mp[y][x]=s;
} scanf("%d",&k);
n=t;
} int dfs(int p)//找出环内最大边
{
vis[p]=true;
int ans=-,op; for(int i=;i<=n;i++){
if(flag[i][p]&&i==pp&&f[p]!=i){e1=i;e2=p;return mp[i][p];}
if(!vis[i]&&flag[i][p]){
f[i]=p;
op=dfs(i); if(op!=-){
if(op<mp[i][p]){e1=i;e2=p;return mp[i][p];}
else return op;
}
}
}
return ans;
} int solve(int p)
{ int tx=,ans=;pp=p;
for(int i=;i<=kk;i++){
tx=;
memset(getr,,sizeof(getr));
// cout<<endl;
// cout<<"第"<<i<<"次轮回"<<endl;
for(int j=;j<=n;j++){
if(flag[p][j]||mp[p][j]==inf){continue;}
memset(vis,,sizeof(vis));
flag[p][j]=flag[j][p]=true;
// cout<<"新增的边 "<<j<<"--"<<p<<endl;
int yj=dfs(p);
// cout<<"删除边的长度 "<<yj<<endl;
getr[tx].pio=j;getr[tx].wei=mp[p][j]-yj;
getr[tx].ex1=e1;getr[tx].ex2=e2;
tx++;
flag[p][j]=flag[j][p]=false;//还原
}
exa.pio=;exa.wei=inf;
for(int i=;i<n;i++){
if(exa.wei>getr[i].wei){exa=getr[i];}
}
// cout<<"最终的决定 "<<exa.ex1<<" "<<exa.ex2<<" "<<exa.pio<<" "<<exa.wei<<endl;
ans+=min(exa.wei,);
flag[p][exa.pio]=flag[exa.pio][p]=true;
flag[exa.ex1][exa.ex2]=flag[exa.ex2][exa.ex1]=false;
}
return ans;
} int main()
{
scan();
int p;
for(int i=;i<=n;i++){
if(!strcmp(name[i],"Park")){p=i;break;}
}
int m=,ans=;
book[p]=p;
for(int i=;i<=n;i++){
if(!book[i]){
m++;
ans+=prim(i);
}
}
// cout<<"初次最小生成树 "<<ans<<endl;
kk=k;
for(int i=;i<=m;i++){
int minn=inf,ss=-;;
for(int j=;j<=n;j++){
if(!flag[p][j]&&!vis[book[j]]&&mp[p][j]!=inf){
if(mp[j][p]<minn){minn=mp[j][p];ss=j;}
}
}
if(minn!=inf){
kk--;
ans+=mp[p][ss];vis[book[ss]]=true;
flag[p][ss]=flag[ss][p]=true;
}
}
// cout<<"最小m度生成树 "<<ans<<endl;
printf("Total miles driven: %d\n",ans+solve(p));
}
POJ 1639 Picnic Planning 最小k度生成树的更多相关文章
- [POJ 1639] Picnic Planning
[题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...
- Picnic Planning POJ - 1639(最小k度生成树)
The Contortion Brothers are a famous set of circus clowns, known worldwide for their incredible abil ...
- POJ 1639 Picnic Planning:最小度限制生成树
题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...
- poj 1639 Picnic Planning 度限制mst
https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...
- POJ 1639 Picnic Planning(最小度限制生成树)
Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...
- poj1639 Picnic Planning,K度限制生成树
题意: 矮人虽小却喜欢乘坐巨大的轿车,车大到能够装下不管多少矮人.某天,N(N≤20)个矮人打算到野外聚餐.为了集中到聚餐地点,矮人A 要么开车到矮人B 家中,留下自己的轿车在矮人B 家,然后乘坐B ...
- poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 10742 Accepted: 3885 ...
- poj1639 Picnic Planning 最小度数限制生成树
题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
[题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...
随机推荐
- size_t的使用
size_t的取值range是目标平台下最大可能的数组尺寸 典型的例子:x64平台下size_t是8位,而x32平台下是4位: int在两个平台下均为4位 所以在使用的时候一定要配置好对应的平台,否则 ...
- Spring MVC 使用介绍(二)—— DispatcherServlet
一.Hello World示例 1.引入依赖 <dependency> <groupId>javax.servlet</groupId> <artifactI ...
- NMAP网络扫描工具的安装与使用
简介 NMAP是一款流行的网络扫描和嗅探工具也是一个强大的端口扫描类安全测评工具,被广泛应用在黑客领域做漏洞探测以及安全扫描,更多的nmap是一个好用的网络工具,在生产和开发中也经常用到,主要做端口开 ...
- nginx压测工具--wrk
基本使用 命令行敲下wrk,可以看到使用帮助 Usage: wrk <options> <url> Options: -c, --connections <N> C ...
- MD5进行解密操作
package com.dyy.test; import java.security.MessageDigest; public class TestMD5Util { /*** * MD5加码 生成 ...
- BZOJ2084[Poi2010]Antisymmetry——回文自动机
题目描述 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的0 ...
- 异步、+回调机制、线程queue、线程Event、协程、单线程实现遇到IO切换
# from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor # import requests # import o ...
- CrawlSpider爬取拉钩
CrawlSpider继承Spider,提供了强大的爬取规则(Rule)供使用 填充custom_settings,浏览器中的请求头 from datetime import datetime imp ...
- mysql 2006错误 导入时
导入数据库报此错误 1.找到my.ini (免安装版的是由于你自己创建的) (安装版的在 C:\ProgramData\MySQL\MySQL Server 8.0 你安装的盘位置) 2.修改参数 ...
- Hdoj 2109.Fighting for HDU 题解
Problem Description 在上一回,我们让你猜测海东集团用地的形状,你猜对了吗?不管结果如何,都没关系,下面我继续向大家讲解海东集团的发展情况: 在最初的两年里,HDU发展非常迅速,综合 ...