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辆车.现在问你在这个限制 ...
随机推荐
- 命名自我规约manual
前端: 所有文件命名都小写,多个单词连接使用 “-” 变量命名规则还是驼峰式,或者在前面加个 “_” SQL: MySQL: 所有命名都小写,无论库.表.还是字段等等,都小写 多个单词之间的分隔,使用 ...
- build/temp.linux-x86_64-2.7/_openssl.c:493:30: fatal error: openssl/opensslv.h: No such file or directory
解决:apt-get install libssl-dev apt install python-dev(这个可能和那个错误关系不大)
- 转 freemarker macro(宏)的使用
有人说用freemarker,但没有用到它的宏(macro),就=没有真正用过freemarker.说的就是宏是freemarker的一大特色. 宏的定义可以查看相关的文档,里面介绍得很清楚,下面来看 ...
- Java拦截器
拦截器,主要用于拦截前端请求,常用于登录检查. 下面是演示使用拦截器拦截未登录的用户访问需要登录的模块情景,使用配置方式实现和注解方式实现代码: 配置方式: 1.web.xml中配置监听器,对于所有的 ...
- TLS/SSL
- P1428 小鱼比可爱
P1428 题目描述 人比人,气死人:鱼比鱼,难死鱼.小鱼最近参加了一个“比可爱”比赛,比的是每只鱼的可爱程度.参赛的鱼被从左到右排成一排,头都朝向左边,然后每只鱼会得到一个整数数值,表示这只鱼的可爱 ...
- Longest Ordered Subsequence POJ - 2533 最长上升子序列dp
题意:最长上升子序列nlogn写法 #include<iostream> #include<cstdio> #include<cstring> #include&l ...
- [NOI2002] 贪吃的九头龙
题目类型:树形DP 传送门:>Here< 题意:有一只九头龙要吃了一颗树,给出一棵\(N\)个节点的带边权的树.九头龙有\(M\)个头,其中一个是大头,大头要吃恰好\(K\)个节点,其他头 ...
- python中的map函数
def f(x): return x * x """将一个全是数字的list变成平方形式""" def f2(): ls = [1, 2, ...
- flask简单登录注册
效果图 发布问答页面需要登录才能访问,没有登录会跳转到登录页面 模板继承,正则验证,数据库迁移,md5加密 mysql 5.7 登录页面 登录后的发布问答页面,右上角会显示用户名和注销 项目代码:码云