POJ 1639 Picnic Planning:最小度限制生成树
题目链接:http://poj.org/problem?id=1639
题意:
给你一个无向图,n个节点,m条边,每条边有边权。
让你求一棵最小生成树,同时保证1号节点的度数<=k。
题解:
最小度限制生成树:
(1)不用与1号节点相连的边,跑一次kruskal,得到了deg个连通块。
(2)选取与1相连的deg条边,并使得边尽可能小,将1与这些连通块连起来,得到了一棵deg度最小生成树。
(3)利用当前的deg度最小生成树,求出deg+1度最小生成树。如此重复至k度最小生成树:
I. 在当前生成树上dfs求出:从1出发到i节点路径上的最大边dp[i](除去与1相连的边)。
II. 枚举与1相连且不在生成树内的边,添加一条能使当前生成树变得最小的边。
III. 如果无论如何都无法将生成树变小,则已求出答案,退出循环。
AC Code:
- #include <iostream>
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- #include <map>
- #define MAX_N 35
- #define MAX_M 905
- #define INF 1000000000
- using namespace std;
- struct Edge
- {
- int s;
- int t;
- int len;
- Edge(int _s,int _t,int _len)
- {
- s=_s;
- t=_t;
- len=_len;
- }
- Edge(){}
- friend bool operator < (const Edge &a,const Edge &b)
- {
- return a.len<b.len;
- }
- };
- int n=,m,k;
- int ans=,deg=;
- int par[MAX_N];
- int lnk[MAX_N];
- int minn[MAX_N];
- int a[MAX_N][MAX_N];
- bool flag[MAX_N][MAX_N];
- Edge dp[MAX_N];
- Edge edge[MAX_M];
- map<string,int> mp;
- int cal_id(const string &s)
- {
- if(mp.count(s)>) return mp[s];
- mp.insert(pair<string,int>(s,++n));
- return n;
- }
- void read()
- {
- cin>>m;
- string s1,s2;
- int v;
- memset(a,-,sizeof(a));
- cal_id("Park");
- for(int i=;i<m;i++)
- {
- cin>>s1>>s2>>v;
- int id1=cal_id(s1);
- int id2=cal_id(s2);
- edge[i]=Edge(id1,id2,v);
- if(a[id1][id2]==-) a[id1][id2]=a[id2][id1]=v;
- else a[id1][id2]=a[id2][id1]=min(a[id1][id2],v);
- }
- cin>>k;
- }
- void init_union_find()
- {
- for(int i=;i<=n;i++)
- {
- par[i]=i;
- }
- }
- int find(int x)
- {
- return par[x]==x ? x : par[x]=find(par[x]);
- }
- void unite(int x,int y)
- {
- int px=find(x);
- int py=find(y);
- if(px==py) return;
- par[px]=py;
- }
- bool same(int x,int y)
- {
- return find(x)==find(y);
- }
- void kruskal()
- {
- init_union_find();
- sort(edge,edge+m);
- memset(flag,false,sizeof(flag));
- for(int i=;i<m;i++)
- {
- Edge temp=edge[i];
- if(temp.s== || temp.t==) continue;
- if(!same(temp.s,temp.t))
- {
- ans+=temp.len;
- unite(temp.s,temp.t);
- flag[temp.s][temp.t]=flag[temp.t][temp.s]=true;
- }
- }
- }
- void cal_mdeg()
- {
- memset(minn,0x3f,sizeof(minn));
- for(int i=;i<=n;i++)
- {
- if(a[][i]!=-)
- {
- int p=find(i);
- if(a[][i]<minn[p])
- {
- minn[p]=a[][i];
- lnk[p]=i;
- }
- }
- }
- for(int i=;i<=n;i++)
- {
- if(minn[i]<INF)
- {
- deg++;
- ans+=minn[i];
- flag[][lnk[i]]=flag[lnk[i]][]=true;
- }
- }
- }
- void dfs(int x,int p)
- {
- for(int i=;i<=n;i++)
- {
- if(flag[x][i] && i!=p)
- {
- if(dp[i].len==-)
- {
- if(a[x][i]>dp[x].len) dp[i]=Edge(x,i,a[x][i]);
- else dp[i]=dp[x];
- }
- dfs(i,x);
- }
- }
- }
- void cal_kdeg()
- {
- for(int j=deg+;j<=k;j++)
- {
- dp[]=Edge(-,-,-INF);
- for(int i=;i<=n;i++)
- {
- if(flag[][i]) dp[i]=Edge(-,-,-INF);
- else dp[i]=Edge(-,-,-);
- }
- dfs(,-);
- int dst,maxn=-INF;
- for(int i=;i<=n;i++)
- {
- if(a[][i]!=- && dp[i].len-a[][i]>maxn)
- {
- maxn=dp[i].len-a[][i];
- dst=i;
- }
- }
- if(maxn<=) return;
- int x=dp[dst].s,y=dp[dst].t;
- flag[x][y]=flag[y][x]=false;
- flag[][dst]=flag[dst][]=true;
- ans-=maxn;
- }
- }
- void solve()
- {
- kruskal();
- cal_mdeg();
- cal_kdeg();
- }
- void print()
- {
- cout<<"Total miles driven: "<<ans<<endl;
- }
- int main()
- {
- read();
- solve();
- print();
- }
POJ 1639 Picnic Planning:最小度限制生成树的更多相关文章
- POJ 1639 Picnic Planning(最小度限制生成树)
Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...
- 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 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...
- poj 1639 Picnic Planning 度限制mst
https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...
- poj1639 Picnic Planning 最小度数限制生成树
题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...
- 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,再 ...
- K度限制MST poj 1639
/* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...
- luogu P5633 最小度限制生成树 wqs二分
LINK:最小度限制生成树 还是WQS二分的模板题 不过相当于我WQS二分的复习题. 对于求出强制k个的答案 dp能做不过复杂度太高了. 世界上定义F(x)表示选出x个的答案 画成图像 其实形成了一个 ...
随机推荐
- leetCode 50.Pow(x, n) (x的n次方) 解题思路和方法
Pow(x, n) Implement pow(x, n). 思路:题目不算难.可是须要考虑的情况比較多. 详细代码例如以下: public class Solution { public doubl ...
- Nginx 变量漫谈
转自:http://blog.sina.com.cn/openrestyNginx 的配置文件使用的就是一门微型的编程语言,许多真实世界里的 Nginx 配置文件其实就是一个一个的小程序.当然,是不是 ...
- Pexpect--example--hive.py解读
python version 2.6.6 ; pexpect 2.3 login方法解读: def login (args, cli_username=None, cli_password=None) ...
- 移动端实用的meta标签
直接上代码,代码自有颜如玉 代码自有黄金屋啊 <meta http-equiv="Content-Type" content="text/html; charset ...
- task10-14
[说明]今天白天有事外出了,晚上会图书馆做了下面的任务,时间有点紧,好多没完成,明天要补上今天的! 一:今日完成 10.插入10条数据,查看有索引和无索引的情况下,Sql语句执行的效率 1)插入数据时 ...
- [JavaScript] Imitate String.Format() in c#
Definition if (!String.prototype.format) { String.prototype.format = function () { var args = argume ...
- 【JavaScript专题】--- 立即执行函数表达式
一 什么是立即执行函数表达式 立即执行函数表达式,其实也可以叫初始化函数表达式,英文名:IIFE,immediately-inovked-function expression.立即执行函数表达式就是 ...
- linux后台开发必备技能
一.linux和os: 1.命令:netstat tcpdump ipcs ipcrm 这四个命令的熟练掌握程度基本上能体现实际开发和调试程序的经验 2.cpu 内存 硬盘 等等与系统性能调试相关的 ...
- python 数据结构中被忽视的小技巧
一.一个包含N个元素的字符串.元组.序列.以及任何可迭代对象均可以拆分成N个单独的“变量” 1.字符串的拆分 #字符串 In [10]: s="abdefg" In [11]: o ...
- LeetCode:三个数的最大乘积【628】
LeetCode:三个数的最大乘积[628] 题目描述 给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积. 示例 1: 输入: [1,2,3] 输出: 6 示例 2: 输入: [1 ...