poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)
Picnic Planning
| Time Limit: 5000MS | Memory Limit: 10000K | |
| Total Submissions: 10742 | Accepted: 3885 |
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
题意:
要求做一个最小生成树,限制条件:给定其中一个点限制其的度不超过 k (最小 k 度限制生成树)。
思路:
第一步,设被限制度数的节点为 v0 ,则在去除 v0 的情况下做最小生成树,可能得到若干个最小生成树(设有 m 棵树);容易想到,这写树必须通过 v0 来连接成一颗树。
第二步,从 v0 引出 m 条边分别连向 m 棵树,则此时得到一个最小 m 度限制生成树,若给定的 k 小于 m 则说明这不是连通图,无法做生成树。
第三步,最多找出 k-m 条 v0 的边去替换树上现有的边;当然,替换必须使树变小才合法。这一步是比较麻烦的,并且若直接枚举的话时间复杂度也较高。每次使用动态规划找出一条贡献最大的边,并替换进树中。直到找齐 k-m 条边、或无法找到合法边是停止。此时得到的就是最小 k 度限制生成树了。
总结:
思路如上十分清晰,可实现起来细节太多了,比较坑的是同一道题不能在不同的OJ AC。在多次调试之后我的代码总算征服了poj、uva、uvalive、scu,但 fzu 却迟迟不能AC。在纵观其他大佬的题解后,发现我的代码已经算强的了....
此题需要注意的是:输入是两点之间可能存在多条边,需要保留最小的边。
代码:
#include<iostream>
#include<map>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstdio>
#define READFILE freopen("D:\\in.txt","r",stdin);
#define INF 1e9+7
using namespace std; class Edge
{
public:
int u, v, w;
Edge(int a=0, int b=0, int c=0):u(a), v(b), w(c) {}
}; map<string, int> mp;
vector<Edge> edges;
Edge dp[105];
int m, n, k, md, grap[105][105], fa[105], mst[105][105], ans=0; bool cmp(Edge a, Edge b)
{
return a.w<b.w;
} void Init()
{
memset(grap, -1, sizeof(grap));//-1不可达
memset(mst, 0, sizeof(mst));
mp.clear();
edges.clear();
n=1, md=0, ans=0, k=0;
int u, v, w;
mp["Park"]=1; string name1, name2;
cin>>m;
for(int i=0; i<m; ++i)
{
cin>>name1>>name2>>w;
if(mp.find(name1)==mp.end())
mp[name1]=n++;
if(mp.find(name2)==mp.end())
mp[name2]=n++;
u=mp[name1], v=mp[name2];
edges.push_back(Edge(u, v, w));
if(grap[u][v]==-1)
grap[u][v]=grap[v][u]=w;
else
grap[u][v]=grap[v][u]=min(grap[u][v], w);
}
cin>>k;
} int Find(int x)
{
if(fa[x]!=x)
return fa[x]=Find(fa[x]);
return x;
} void Union(int a, int b)
{
int x=Find(a);
int y=Find(b);
if(x!=y)
fa[x]=y;
} int Kruskal()//去除限制点生成md棵最小生成树
{
int res=0;
sort(edges.begin(), edges.end(), cmp);
for(int i=0; i<=n; ++i)
fa[i]=i;
for(int i=0; i<edges.size(); ++i)
{
Edge& e=edges[i];
if(e.u==1 || e.v==1 || Find(e.u)==Find(e.v)) continue;
Union(e.u, e.v);
mst[e.u][e.v]=mst[e.v][e.u]=grap[e.u][e.v];
res+=grap[e.u][e.v];
}
return res;
} int mmst()//生成最小md度限制生成树
{
int minw[25], minv[25], res=0;
for(int i=0; i<=n; ++i) minw[i]=INF;
for(int i=2; i<=n; ++i)
if(grap[1][i]!=-1)
{
int x=Find(i);
if(minw[x] > grap[1][i])
{
minw[x]=grap[1][i];
minv[x]=i;
}
}
for(int i=1; i<=n; ++i)
if(minw[i]!=INF)
{
md++;
mst[1][minv[i]]=mst[minv[i]][1]=1;
res+=grap[1][minv[i]];
}
return res;
} void dfs(int x,int fa)
{
for(int i=2; i<=n; i++)
if(mst[x][i] && i!=fa)
{
if(dp[i].w==-1)
{
if(grap[x][i]<dp[x].w)
{
dp[i].u=dp[x].u;
dp[i].v=dp[x].v;
dp[i].w=dp[x].w;
}
else
dp[i].u=x,dp[i].v=i,dp[i].w=grap[x][i];
}
dfs(i,x);
}
}
int mkst()
{
int res=0;
for(int i=md+1; i<=k; i++)
{
for(int j=0; j<=n; ++j)
dp[j].w=-1;
dp[1].w=-INF;
for(int j=2; j<=n; j++)
if(mst[1][j])
dp[j].w=-INF;
dfs(1,-1);
int t=0,minn=INF;
for(int j=2; j<=n; j++)
if(grap[1][j]!=-1&&grap[1][j]-dp[j].w<minn)
{
minn=grap[1][j]-dp[j].w;
t=j;
}
if(minn>=0)
break;
mst[1][t]=mst[t][1]=1;
int x=dp[t].u,y=dp[t].v;
mst[x][y]=mst[y][x]=0;
res+=minn;
}
return res;
} int main()
{
//READFILE
int t;
t=1;//有的oj多组数据此处改为cin>>t即可
while(t--)
{
Init();
int ans1=Kruskal();
int ans2=mmst();
int ans3=mkst();
ans=ans1+ans2+ans3;
cout<<"Total miles driven: "<<ans<<endl;
if(t)cout<<endl;
}
return 0;
}
poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)的更多相关文章
- POJ 1639 Picnic Planning 最小k度生成树
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions:11615 Accepted: 4172 D ...
- poj1639 Picnic Planning 最小度数限制生成树
题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...
- POJ1639 - Picnic Planning
原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...
- POJ 1861 ——Network——————【最小瓶颈生成树】
Network Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 15268 Accepted: 5987 Specia ...
- bzoj2395[Balkan 2011]Timeismoney最小乘积生成树
所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...
- HDU5697 刷题计划 dp+最小乘积生成树
分析:就是不断递归寻找靠近边界的最优解 学习博客(必须先看这个): 1:http://www.cnblogs.com/autsky-jadek/p/3959446.html 2:http://blog ...
- 【UVA 11354】 Bond (最小瓶颈生成树、树上倍增)
[题意] n个点m条边的图 q次询问 找到一条从s到t的一条边 使所有边的最大危险系数最小 InputThere will be at most 5 cases in the input file.T ...
- 算法提高 最小方差生成树(Kruskal)_模板
算法提高 最小方差生成树 时间限制:1.0s 内存限制:256.0MB 问题描述 给定带权无向图,求出一颗方差最小的生成树. 输入格式 输入多组测试数据.第一行为N,M,依次是 ...
- 【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树
链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...
随机推荐
- nginx实战(1):宝塔设置反向代理
以下操作适用于默认80端口转其他地址非80端口情况. 添加网站 注意:因我只是拿来当反向代理来使用,所PHP为纯静态模式. 开启反向代理 注:目标URL为最终目的地,发送域名为默认,如设置后无效则修改 ...
- spring mvc(3) DispatcherServlet
通过前面的例子,我们实现了spring mvc模式,那么在spring mvc模式下请求是如何被执行最终返回页面的呢? 从服务器收到请求开始,执行流程如下: 1.服务器接收请求,根据web.xml的配 ...
- Django request
''' 1.HttpRequest.GET 一个类似于字典的对象,包含 HTTP GET 的所有参数.详情请参考 QueryDict 对象. 2.HttpRequest.POST 一个类似于字典的对象 ...
- ch4inrulz: 1.0.1靶机渗透
ch4inrulz: 1.0.1靶机渗透 扫描主机端口,还行啦四个开放的端口,8011和80端口都运行着web服务. 80端口下的robots.txt告诉我们什么都没有 在8011端口的apache服 ...
- GIT学习与GIEE(码云体验)
GIT 是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理.Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件 ...
- 从四个问题透析Linux下C++编译&链接
摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...
- 基础篇:详解JAVA对象实例化过程
目录 1 对象的实例化过程 2 类的加载过程 3 触发类加载的条件 4 对象的实例化过程 5 类加载器和双亲委派规则,如何打破双亲委派规则 欢迎指正文中错误 关注公众号,一起交流 参考文章 1 对象的 ...
- 高并发场景-请求合并(二)揭秘HystrixCollapser-利用Queue和线程池异步实现
背景 在互联网的高并发场景下,请求会非常多,但是数据库连接池比较少,或者说需要减少CPU压力,减少处理逻辑的,需要把单个查询,用某些手段,改为批量查询多个后返回. 如:支付宝中,查询"个人信 ...
- 给子元素设置margin-top无效果的一种解决方法
在写一个登陆界面的时候,设置登录按钮的margin-top时出了问题 先是这么写的 <div style="margin-top:30px"> <a style= ...
- xshell选项卡不见了
最近使用xshell的时候发现建立多个选项卡的时候,因为没有选项卡,所以不能切换. 弄了好一会儿才弄出来 点击会话选项卡或者Ctrl + Shift + T可以调出来