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("网 ...
随机推荐
- DVWA sql注入low级别
DVWA sql注入low级别 sql注入分类 数字型注入 SELECT first_name, last_name FROM users WHERE user_id = $id 字符型注入 SELE ...
- spring mvc(4) HandlerMapping
在前面一节里提到,DispatcherServlet在接收到请求后,通过HandlerMapping找到处理请求对应的Controller(其实处理请求器并不一定是Controller,还可以是Htt ...
- HTML+CSS实现大盒子在小盒子的展示范围内进行滚动展示
HTML+CSS实现大盒子在小盒子的展示范围内进行滚动展示 1.效果展示: 2.主要代码:样式: overflow:auto; 3.如果想要消除对应的滚动条: .out::-webkit-scroll ...
- 一篇带你快速入门ansible和使用
#基本概述 ansible是一款开源自动化工具,基于python paramiko模块开发,分布式,无需客户端 官网网址:https://www.ansible.com 官方文档:https://do ...
- 这么设计,Redis 10亿数据量只需要100MB内存
本文主要和大家分享一下redis的高级特性:bit位操作. 本文redis试验代码基于如下环境: 操作系统:Mac OS 64位 版本:Redis 5.0.7 64 bit 运行模式:standalo ...
- js自动生成条形码插件-JsBarcode
JsBarcode.html <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- Centos-退出抽取设备-eject
eject 退出抽取设备,如光驱或磁带,如果设备已经挂载,则卸载设备 相关选项 -q 退出磁盘 -r 退出光盘 -d 显示默认设备
- Centos-系统任务队列信息-uptime
uptime 显示系统的当前时间.系统从启动到当前运行时间.当前总共在线用户.系统1.5.15分钟负载情况
- python-代数式括号有效性检验
思路: 利用栈实现代数式中括号有效行的的检验: 代码: class mychain(object): #利用链表建立栈,链表为父类 length=0 def __init__(self,value=N ...
- >>8) & 0xFF中的 >> 和 &0xFF 的作用
参考:https://blog.csdn.net/iamgamer/article/details/79354617 其中有两个位运算,一个是>>,一个是&. 0xff的作用一: ...