解法参考的论文: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. java 多线程间通信(二)

    传统的线程通信 Object提供了三个方法wait(), notify(), notifyAll()在线程之间进行通信,以此来解决线程间执行顺序等问题. wait():释放当前线程的同步监视控制器,并 ...

  2. JQuery 获取表格table所有行第一列

    main_table 是表ID $("#main_table tr").find("td:eq(0)")

  3. 深入学习Redis持久化

    一.Redis高可用概述 在介绍Redis高可用之前,先说明一下在Redis的语境中高可用的含义. 我们知道,在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常 ...

  4. dotNET面试(一)

    1.列举ASP.NET 页面之间传递值的几种方式. 1).使用QueryString, 如....?id=1; response. Redirect().... 2).使用Session变量 3).使 ...

  5. brew install ''package卡在Updating Homebrew

    关闭自动更新: export HOMEBREW_NO_AUTO_UPDATE=true

  6. ida吧

    经过IDA反编译后的代码是:int __cdecl Ompress(void *Dst, int a2, int a3, int a4)//dst( [esp+24h][ebp+4h] );a2([e ...

  7. Struts 2中的constant详解【转载】

    通过对这些属性的配置,可以改变Struts 2 框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成. struts.xml 1.&l ...

  8. static 关键字详解(用途、误区、面试题)

    static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列 ...

  9. Vue学习笔记【28】——Vue路由(使用 children 属性实现路由嵌套)

    使用 children 属性实现路由嵌套   <div id="app">    <router-link to="/account"> ...

  10. Panel

    在Panel上绘图的实现 近期制作了FDS的一个建模工具,由于知识有限,做出的效果是2D的.昨天上课的时候看老师画一个长方体,突然想到,为什么不给普通的2D图形加画上几条直线,就能实现2D图形的3D视 ...