poj 1639 Picnic Planning 度限制mst
https://vjudge.net/problem/POJ-1639
题意:
有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但是终点只有一个,并且终点能停的车的数量是有限制的,问最少走的路是多少。
思路:
因为终点的停车的数量是有限制的,所以终点的度是有限制的,又因为这题可以用最小生成树解决,所以就是度限制最小生成树。
度限制最小生成树求解思想并不复杂,首先我们把有度限制的点给忽略,然后给每一个连通分量求最小生成树,最后把每一个连通分量中与有度限制的点的距离最小的点与度限制点连接,假设有m个连通分量。
那么我们现在求出了m限制的最小生成树,假如限制数k < m,那么就无解。
当k >= m时,我们可以在m度限制mst的基础上,求m + 1,m + 2。。。k度限制最小生成树,求法也不是很难懂,但是程序就很难写了Orz。
如何求呢?枚举每一条未在生成树中与(现在我们把度限制点叫做R点)R点相连的边,然后把边加入生成树,必然会形成环,然后把环中与R点不相连的权值最大的边去掉,枚举之后的最小值就是m+1度限制最小生成树的值。然后依次求到k限制mst,求其中的最小值。
但是,依次枚举的话时间复杂度非常高,所以我们要优化。这时就用到了动态规划的思想。将与R点到其它点的边权值最大求出,之后加边的时候,直接替换就可以了。
转移方程 dp[v] = max(dp[father(v)],w(v , father(v)));
看不懂就多看几遍Orrrrrrrrrrrrrrrrrrrrrrrrz。
代码:
- #include <stdio.h>
- #include <algorithm>
- #include <iostream>
- #include <string.h>
- #include <map>
- #include <string>
- using namespace std;
- const int inf = 0x3f3f3f3f;
- struct edge
- {
- int x,y;
- int v;
- } a[],dp[];
- map<string,int> mmp;
- bool flag[][];
- int par[];
- int g[][];
- int ans;
- int num;
- int du,lim;
- int fin(int x)
- {
- if (x == par[x]) return x;
- else return par[x] = fin(par[x]);
- }
- void unit(int x,int y)
- {
- x = fin(x);
- y = fin(y);
- if (x == y) return;
- par[x] = y;
- }
- void dfs(int cur,int pre)
- {
- for (int i = ;i <= num;i++)
- {
- if (i != pre && flag[cur][i])
- {
- if (dp[i].v == -)
- {
- if (dp[cur].v > g[cur][i])
- {
- dp[i] = dp[cur];
- }
- else
- {
- dp[i].x = cur;
- dp[i].y = i;
- dp[i].v = g[cur][i];
- }
- }
- dfs(i,cur);
- }
- }
- }
- void solve(void)
- {
- for (int i = du + ;i <= lim;i++)
- {
- memset(dp,-,sizeof(dp));
- dp[].v = -inf;
- for (int j = ;j <= num;j++)
- if (flag[j][]) dp[j].v = -inf;
- dfs(,-);
- int mi = inf,tmp;
- for (int j = ;j <= num;j++)
- {
- if (g[][j] != -)
- {
- if (mi > g[][j] - dp[j].v)
- {
- mi = g[][j] - dp[j].v;
- tmp = j;
- }
- }
- }
- if (mi >= ) break;
- ans += mi;
- int x = dp[tmp].x,y = dp[tmp].y;
- flag[x][y] = flag[y][x] = ;
- flag[][tmp] = flag[tmp][] = ;
- }
- }
- int get_num(string aa)
- {
- if (mmp[aa]) return mmp[aa];
- else
- {
- mmp[aa] = ++num;
- return num;
- }
- }
- bool cmp(edge aa,edge bb)
- {
- return aa.v < bb.v;
- }
- int main()
- {
- num = ;
- mmp["Park"] = ;
- memset(g,-,sizeof(g));
- int n;
- scanf("%d",&n);
- for (int i = ;i < n;i++)
- {
- string aa,bb;
- int v;
- cin >> aa >> bb;
- scanf("%d",&v);
- int x = get_num(aa),y = get_num(bb);
- if (g[x][y] == -) g[x][y] = g[y][x] = v;
- else g[x][y] = g[y][x] = min(v,g[x][y]);
- a[i].x = x;
- a[i].y = y;
- a[i].v = g[x][y];
- }
- for (int i = ;i <= num;i++) par[i] = i;
- scanf("%d",&lim);
- sort(a,a+n,cmp);
- for (int i = ;i < n;i++)
- {
- int x = a[i].x,y = a[i].y;
- if (x == || y == ) continue;
- if (fin(x) == fin(y)) continue;
- ans += a[i].v;
- unit(x,y);
- flag[x][y] = flag[y][x] =;
- }
- int minn[],tmp[];
- memset(minn,inf,sizeof(minn));
- for (int i = ;i <= num;i++)
- {
- int rt = fin(i);
- if (g[][i] != -)
- {
- if (g[][i] < minn[rt])
- {
- minn[rt] = g[][i];
- tmp[rt] = i;
- }
- }
- }
- for (int i = ;i <= num;i++)
- {
- if (minn[i] != inf)
- {
- du++;
- flag[][tmp[i]] = flag[tmp[i]][] = ;
- ans += minn[i];
- }
- }
- solve();
- printf("Total miles driven: %d\n",ans);
- return ;
- }
poj 1639 Picnic Planning 度限制mst的更多相关文章
- POJ 1639 Picnic Planning 最小k度生成树
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions:11615 Accepted: 4172 D ...
- POJ 1639 Picnic Planning:最小度限制生成树
题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...
- [POJ 1639] Picnic Planning
[题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...
- POJ 1639 Picnic Planning(最小度限制生成树)
Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...
- poj 1639 最小k度限制生成树
题目链接:https://vjudge.net/problem 题意: 给各位看一下题意,算法详解看下面大佬博客吧,写的很好. 参考博客:最小k度限制生成树 - chty - 博客园 https:/ ...
- K度限制MST poj 1639
/* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...
- poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 10742 Accepted: 3885 ...
- POJ1639 - Picnic Planning
原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
[题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...
随机推荐
- 《Linux命令行与shell脚本编程大全》- 读书笔记1 - 基本的bash shell 命令
这本书买了好久了,除了刚到手的那几天翻看了一下以外,竟然到今天都没有看过.突然想要写一个shell脚本,发现什么也不会,是时候开始学习了,今天先把最简单的一章再看一遍顺便做一些笔记,明天继续后面的! ...
- SQL server 2008 安装提示:属性不匹配
问题 安装SQL server 2008提示属性不匹配 解决方案 确保C盘以及其子文件夹C:\Program Files\Microsoft SQL Server和C:\Program Files ( ...
- linux内核管理
一 linux组成:kernel.库.rootfs.程序 1.kernel的功能: 1) kernel提供的功能都通过系统调用给用户接口 2) kernel包括:进程管理 .内存管理 .网络管理 ...
- 【Python】excel读写操作 xlrd & xlwt
xlrd ■ xlrd xlrd模块用于读取excel文件内容 基本用法: workbook = xlrd.open_workbook('文件路径') workbook.sheet_names() # ...
- zabbix监控redis性能
创建采集脚本 mkdir -p /etc/zabbix/scripts chown -R zabbix.root /etc/zabbix/scripts vim redis_status.sh #! ...
- STL --> 高效使用STL
高效使用STL 仅仅是个选择的问题,都是STL,可能写出来的效率相差几倍: 熟悉以下条款,高效的使用STL: 一.当对象很大时,建立指针的容器而不是对象的容器 1)STL基于拷贝的方式的来工作,任 ...
- Jmeter 前置处理器 BeanShell_PreProcessor 适用思考
首先摘抄一段官方文档的话: Before invoking the script, some variables are set up in the BeanShell interpreter: lo ...
- 慢查询日志分析(mysql)
开启慢查询日志之后,慢查询sql会被存到数据库系统表mysql.slow_log或是文件中,可参考.有两个工具可以帮助我们分析输出报告,分别是mysqldumpslow和pt-query-digest ...
- Entity Framework——并发策略
使用EF框架遇到并发时,一般采取乐观并发控制. 1支持并发检验 为支持并发检验,需要对实体进行额外的设置.默认情况下是不支持并发检验的.有以下两种方式: 方式名称 说明 时间戳注解/行版本 使用Tim ...
- 团队作业5-测试与发布(AIpha版本)
对于已完成的项目我们进行了诸多测试,找到了少许bug,对着这些bug我们在改进的基础上提出了新的目标. 1,测试环境:个人笔记本.个人台式机.环境windows7.网络校园网加移动vpn,浏览器360 ...