解法参考的论文: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 度数限制最小生成树的更多相关文章

  1. POJ 1639 Picnic Planning 最小k度生成树

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions:11615   Accepted: 4172 D ...

  2. POJ 1639 Picnic Planning:最小度限制生成树

    题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...

  3. POJ 1639 Picnic Planning(最小度限制生成树)

    Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...

  4. [POJ 1639] Picnic Planning

    [题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...

  5. poj 1639 Picnic Planning 度限制mst

    https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...

  6. UVA1537 Picnic Planning(思维+最小生成树)

    将1号点从图中去掉过后,图会形成几个连通块,那么我们首先可以在这些连通块内部求最小生成树. 假设有\(tot\)个连通块,那么我们会从1号点至少选\(tot\)个出边,使得图连通.这时我们贪心地选择最 ...

  7. poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10742   Accepted: 3885 ...

  8. POJ1639 - Picnic Planning

    原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...

  9. 限制某个顶点度数的最小生成树 poj1639

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10642   Accepted: 3862 ...

随机推荐

  1. Vue小白篇 - Vue 的指令系统 (1) v-text、v-html

    v-text:相当于innerText v-html:相当于innerHTML <div id="box"> {{ msg }} <div v-text=&quo ...

  2. go语言从例子开始之Example7.switch分支结构

    switch ,方便的条件分支语句 package main import "fmt" import "time" func main() { 一个基本的 sw ...

  3. 什么是SolrCloud

    1.1 什么是SolrCloud SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud.当一个系统的索引数据量少的时候 ...

  4. 一次goldengate故障引发的操作系统hang起,HA自动切换

    现场: 跑着数据库的主机A报警应用连接不上数据库,我们无法ssh到主机.第一反应是通过telnet到远程控制口,发现数据库资源和硬件资源在被切换到HA架构的主机B(备机,通常性能比主机A的差,抗不住应 ...

  5. 【串线篇】SpringMvc视图解析

    一. 请求处理方法执行完成后,最终返回一个 ModelAndView 对象.对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ...

  6. Java中Calendar类的常用方法(对时间进行计算的类)

    例子: /**** * 传入具体日期 ,返回具体日期增加一个月. * @param date 日期(2017-04-13) * @return 2017-05-13 * @throws ParseEx ...

  7. enumerate()(Python)

    >>> E=enumerate('spam') >>> E <enumerate object at 0x1021ceca8> >>> ...

  8. VC连接SQLite3的方法(MFC封装类)

    SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,支持跨平台,操作简单,能够使用很多语言直接创建数据库.官方网站:www.sqlite.org 在VC环境下编写连接SQLite的 ...

  9. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡(后缀自动机)

    传送门 解题思路 因为叶节点不超过\(20\)个,所以可以枚举这些叶节点,并把这些节点当做根扫整棵树.可以证明所有的子串一定可以被便利到,然后可以对这些串建广义后缀自动机.\(dfs\)的时候要记录一 ...

  10. Red Hat Enterprise Linux 7.x新特性

    Red Hat Enterprise Linux 7.x新特性 RHEL7新特性简介 1.      RHEL7目前支持架构 64-bit AMD.64-bit Intel.IBM POWER.IBM ...