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个的答案 画成图像 其实形成了一个 ...
随机推荐
- member access within misaligned address 0x000000000031 for type 'struct ListNode', which requires 8 byte alignment
在做LeetCode的two sum题目的时候,提交代码遇到了如题的runtime error,后来在一篇博客上看到了解决方法. 现有如下结构体: struct ListNode { int val; ...
- JSP开发中的基础语法
JSP 语法 JSP开发中的基础语法. 脚本程序 脚本程序可以包含任意量的Java语句.变量.方法或表达式,只要它们在脚本语言中是有效的. 脚本程序的语法格式: <% 代码片段 %> 或者 ...
- PYTHON测试邮件系统弱密码
#-*- coding:utf-8 -*- #测试公司邮件系统弱密码, from email.mime.text import MIMEText import smtplib #弱密码字典 passL ...
- react-native create-react-app创建项目报错SyntaxError: Unexpected end of JSON input while parsing near '...ttachment":false,"tar' npm代理
SyntaxError: Unexpected end of JSON input while parsing near '...ttachment":false,"tar' 错误 ...
- HTTP Status 404(The requested resource is not available)
这个问题之前在部署项目工程的时候经常遇见,今天我大致总结下出现这样的原因: 1.首先想到的是没有部署项目,但是你却在访问这个,这种不是很常见(对于老手). 2.其次是URL输入错误: 排错方法: 首先 ...
- 【BZOJ2115】[Wc2011] Xor 高斯消元求线性基+DFS
[BZOJ2115][Wc2011] Xor Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ...
- 【BZOJ2724】[Violet 6]蒲公英 分块+二分
[BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...
- 【bzoj2226】[Spoj 5971] LCMSum 欧拉函数
题目描述 Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + LCM(n,n), where LCM(i,n) denotes the Leas ...
- windy数(简单数位DP)
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6306 Solved: 2810[Submit][Sta ...
- elasticsearch从入门到出门-05-集群之踩坑
自己搭的集群, 设备: win10 + ubuntu 16 的虚拟机一个: 下载的版本:elasticsearch-5.2.0 win10 解压下就好了,不说了. ubuntu 上,我想说多了都是泪! ...