POJ-1639 Picnic Planning 度数限制最小生成树
解法参考的论文:https://wenku.baidu.com/view/8abefb175f0e7cd1842536aa.html
觉得网上的代码好像都是用邻接矩阵来实现的,觉得可能数据量大了会比较慢。于是自己写了一遍。
实现细节可以看代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
const int N=+;
const int INF=0x3f3f3f3f;
int n,m,k,ans,fa[N];
struct edge{
int x,y,z;
bool used;
edge() {}
edge(int x,int y,int z) : x(x),y(y),z(z) { used=; }
bool operator < (const edge &rhs) const {
return z<rhs.z;
}
}e[N];
map<string,int> mp;
vector<int> G[N]; int getfa(int x) { return x==fa[x] ? x : fa[x]=getfa(fa[x]); } void kruskal() {
sort(e+,e+m+);
for (int i=;i<=n;i++) fa[i]=i;
for (int i=;i<=m;i++) {
int fx=getfa(e[i].x),fy=getfa(e[i].y);
if (e[i].x== || e[i].y== || fx==fy) continue;
fa[fy]=fa[fx];
e[i].used=;
ans+=e[i].z;
}
} int Max[N];
void dfs(int x,int f) {
for (int i=;i<G[x].size();i++) {
int y; if (e[G[x][i]].x==x) y=e[G[x][i]].y; else y=e[G[x][i]].x;
if (!e[G[x][i]].used || y==f) continue;
if (x!=) //这个很重要:去掉的边必须和V0不相连(否则会使得根节点度数减少)
if (Max[x]== || e[G[x][i]].z>e[Max[x]].z) Max[y]=G[x][i];
else Max[y]=Max[x];
dfs(y,x);
}
} int cnt=,Min[N];
void solve() {
memset(Min,,sizeof(Min));
for (int i=;i<G[].size();i++) { //把各个MST森林最小边连到根节点 变成一棵树
int ty;
if (e[G[][i]].x==) ty=getfa(e[G[][i]].y);
else ty=getfa(e[G[][i]].x);
if (Min[ty]== || e[G[][i]].z<e[Min[ty]].z) Min[ty]=G[][i];
}
for (int i=;i<=n;i++)
if (Min[i]) { cnt++; ans+=e[Min[i]].z; e[Min[i]].used=; } for (int i=cnt+;i<=k;i++) { //拓展根节点度数
memset(Max,,sizeof(Max));
dfs(,); //dfs找每个点到根节点的路径上的最长边
int minn=INF,New,Old;
for (int j=;j<G[].size();j++)
if (!e[G[][j]].used) {
int y; if (e[G[][j]].x==) y=e[G[][j]].y; else y=e[G[][j]].x;
if (Max[y]==) continue;
int tmp=e[G[][j]].z-e[Max[y]].z;
if (tmp<minn) { //记录本次结点拓展最大的收益
minn=tmp;
New=G[][j]; Old=Max[y];
}
}
if (minn>=) break;
ans+=minn;
e[New].used=; e[Old].used=; //替换最长边
}
} int main()
{
cin>>m;
string s1,s2; int x,y,z;
n=; mp["Park"]=;
for (int i=;i<=m;i++) {
cin>>s1>>s2>>z;
if (!mp.count(s1)) mp[s1]=++n;
if (!mp.count(s2)) mp[s2]=++n;
x=mp[s1]; y=mp[s2];
e[i]=edge(x,y,z);
}
cin>>k; kruskal(); //先忽略根节点做一次MST 得到MST森林
for (int i=;i<=m;i++) { G[e[i].x].push_back(i); G[e[i].y].push_back(i); }
solve(); //拓展根节点度数得到更小的MST printf("Total miles driven: %d\n",ans);
return ;
}
POJ-1639 Picnic Planning 度数限制最小生成树的更多相关文章
- 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(最小度限制生成树)
Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...
- [POJ 1639] Picnic Planning
[题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...
- poj 1639 Picnic Planning 度限制mst
https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...
- UVA1537 Picnic Planning(思维+最小生成树)
将1号点从图中去掉过后,图会形成几个连通块,那么我们首先可以在这些连通块内部求最小生成树. 假设有\(tot\)个连通块,那么我们会从1号点至少选\(tot\)个出边,使得图连通.这时我们贪心地选择最 ...
- 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,再 ...
- 限制某个顶点度数的最小生成树 poj1639
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 10642 Accepted: 3862 ...
随机推荐
- send csv to es with filebeat
## filebeat *.csv 2019-11-30 23:27:50,111111,222222,VIEW,333333333333 filebeat filebeat.inputs:- pat ...
- 【报错】解决logstash tracking_column not found in dataset. {:tracking_column=>"updated_time"}问题
今天用logstash同步数据库记录到elasticsearch时候出现错误,错误信息如下: [2019-10-12T23:51:00,529][WARN ][logstash.inputs.jdbc ...
- 基于 Scrapy-redis 两种形式的分布式爬虫
基于 Scrapy-redis 两种形式的分布式爬虫 .caret, .dropup > .btn > .caret { border-top-color: #000 !important ...
- 【转】Java里如何实现线程间通信
正常情况下,每个子线程完成各自的任务就可以结束了.不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了. 本文涉及到的知识点:thread.join(), object.w ...
- mui使用总结
mui是一个高性能的HTML5开发框架,从UI到效率,都在极力追求原生体验:这个框架自身有一些规则,刚接触的同学不很熟悉,特总结本文:想了解mui更详细的信息,请访问mui官网 DOM结构 关于mui ...
- .net从服务端下载文件(可以断点续传)
public void DownFile(string guid) { var fileTransfer = new FileTransfer(); var directoryPath = Path. ...
- AcWing 226. 233矩阵 (矩阵快速幂+线性递推)打卡
题目:https://www.acwing.com/problem/content/228/ 题意:有一个二维矩阵,这里只给你第一行和第一列,要你求出f[n][m],关系式有 1, f[0][ ...
- [CSP-S模拟测试72]题解
A.简单的序列 遇到括号匹配,先将左右括号转化为1和-1. 那么一个括号序列合法的必要条件:总和为0且所有时刻前缀和$\ge 0$. 用dp预处理出长度为$i$,总和为$j$的括号序列数量.那么如果p ...
- 【c#技术】一篇文章搞掂:水晶报表
更新数据源 应该先从[数据库]——[数据库专家]——[刷新]——[数据库]——[验证数据库] 必须先刷新,不然验证数据库无效 XP下,打开水晶报表提示无法创建目录或文件,删除临时目录Temp中文件即可 ...
- ios 最全的常用字符串操作
1.将NSData / NSString转化 1 2 3 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; // 将字符串 ...