Picnic Planning POJ - 1639 限制顶点度数的MST
2017-10-09 17:00
344 查看
题意:
有n个兄弟去野餐,目的地为Park。每个人可以选择直接去Park,也可以选择去其他人家,和他一起坐车去Park。
每个人家的停车位没有限制,但是Park的停车数不能超过k。问所有人的最短路程。
思路
上手可能觉得题目很难,但是分解一下就会发现很简单.
①根节点的度有限制的生成树或许不好写,但度最小的生成树却很简单.
②有一种方法可以 将根节点度为i的最小生成树变成成i+1的MST
方法如下:
1. 用dp预处理出当前生成树中从V0到点i的路径上与V0无关联的权值最大的边,记为dp[i].d,该边的两端点记为dp[i].u和dp[i].v。
2. 对于一个不在生成树中的边(V0, v) 如果将该边加入生成树中,则一定会得到一个环。此时我们删掉环中权值最大的边,即(1)中预处理得到的dp[v],得到一棵m+1度的最小生成树。
我们一直做操作② 直到根节点的度不能在增加或者增加之后树不小反大
代码如下
有n个兄弟去野餐,目的地为Park。每个人可以选择直接去Park,也可以选择去其他人家,和他一起坐车去Park。
每个人家的停车位没有限制,但是Park的停车数不能超过k。问所有人的最短路程。
思路
上手可能觉得题目很难,但是分解一下就会发现很简单.
①根节点的度有限制的生成树或许不好写,但度最小的生成树却很简单.
②有一种方法可以 将根节点度为i的最小生成树变成成i+1的MST
方法如下:
1. 用dp预处理出当前生成树中从V0到点i的路径上与V0无关联的权值最大的边,记为dp[i].d,该边的两端点记为dp[i].u和dp[i].v。
2. 对于一个不在生成树中的边(V0, v) 如果将该边加入生成树中,则一定会得到一个环。此时我们删掉环中权值最大的边,即(1)中预处理得到的dp[v],得到一棵m+1度的最小生成树。
我们一直做操作② 直到根节点的度不能在增加或者增加之后树不小反大
代码如下
/* * Author : Echo * Email : 1666424499@qq.com * Description : * Created Time : 2017/10/7 8:43:20 * Last Modify : 2017/10/9 16:39:46 * File Name : a.cpp */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> using namespace std; const int INF =1e9; const int maxn=30; const int maxm=2e4; struct edge{ int u,v,value; }an[maxm],dp[maxm];//an:路,dp:最长路 int n;//路条数 int cnt=0,du=0,size=0;//cnt:人数,du:根节点的度,size:根节点的上限 map<string,int>mp; int mmp[maxn][maxn];//邻接矩阵 int tre[maxn][maxn];//生成树 int pa[maxn];//并查集的父节点 int minn(int a,int b){ return a<b?a:b; } bool cmp(edge a,edge b){ return a.value<b.value; } int getP(int a){ if(pa[a]==0||pa[a]==a) return a; pa[a]=getP(pa[a]); return pa[a]; } int ans=0; void mst(){//生成树-根度数最小的 sort(an,an+n,cmp); //去除根节点 for(int i=0;i<n;i++){ int u=an[i].u; int v=an[i].v; int value=an[i].value; if(u==1||v==1)continue; int pu=getP(u); int pv=getP(v); if(pu==pv)continue; pa[pu]=pv; ans+=value; tre[u][v]=tre[v][u]=1; } //加上根节点 for(int i=0;i<n;i++){ int u=an[i].u; int v=an[i].v; int value=an[i].value; if(u!=1&&v!=1)continue; int pu=getP(u); int pv=getP(v); if(pu==pv)continue; du++; pa[pu]=pv; ans+=value; tre[u][v]=tre[v][u]=1; } } int dfs(int u,int pre){ for(int i=2;i<=cnt;i++){ if(i==pre||tre[u][i]==0) continue; if(dp[i].value==-1){ if(dp[u].value>mmp[u][i]) dp[i]=dp[u]; else { dp[i].u=u; dp[i].v=i; dp[i].value=mmp[u][i]; } } dfs(i,u); } } int cal(){ for(int i=du+1;i<=size;i++){ for(int i=1;i<=cnt;i++) dp[i].value=-1; dfs(1,-1); int minnum=INF; int u; for(int i=2;i<=n;i++){ if(minnum>mmp[1][i]-dp[i].value){ minnum=mmp[1][i]-dp[i].value; u=i; } } if(minnum>0)continue; ans+=minnum; tre[1][u]=tre[u][1]=1; tre[dp[u].u][dp[u].v]=0; tre[dp[u].v][dp[u].u]=0; } } int main(){ cin>>n; mp["Park"]=1; cnt=1; memset(mmp,0x3f,sizeof(mmp)); for(int i=0;i<n;i++){ string a,b; int u,v,value; cin>>a>>b>>value; if(mp[a]==0)mp[a]=++cnt; if(mp[b]==0)mp[b]=++cnt; u=mp[a]; v=mp[b]; mmp[u][v]=minn(mmp[u][v],value); mmp[v][u]=minn(mmp[v][u],value); an[i].u=u; an[i].v=v; an[i].value=value; } cin>>size; mst(); cal(); printf("Total miles driven: %d\n",ans); return 0; } /* 10 Alphonzo Bernardo 32 Alphonzo Park 57 Alphonzo Eduardo 43 Bernardo Park 19 Bernardo Clemenzi 82 Clemenzi Park 65 Clemenzi Herb 90 Clemenzi Eduardo 109 Park Herb 24 Herb Eduardo 79 3 Total miles driven: 183 */
相关文章推荐
- POJ1639 Picnic Planning —— 根节点度数有限制的最小生成树
- 【POJ】1639 Picnic Planning 度限制最小生成树
- poj_1639 Picnic Planning(度限制最小生成树)
- Picnic Planning poj 1639 k度限制生成树
- poj 1639 Picnic Planning k限制生成树问题
- poj 1639 Picnic Planning 单度限制的最小生成树
- POJ 1639 Picnic Planning 【最小度限制生成树】
- POJ 1639 Picnic Planning【度限制最小生成树】
- POJ 1639 Picnic Planning(度限制最小生成树)
- POJ 1639 Picnic Planning(有限制的最小生成树)
- POJ 1639 Picnic Planning【度限制最小生成树】
- poj1639 Picnic Planning 限制顶点度数的MST
- poj1639 Picnic Planning 最小度数限制生成树
- poj1639 Picnic Planning 最小度数限制生成树
- poj1639 Picnic Planning 最小度数限制生成树
- [POJ 1639]Picnic Planning
- POJ1639-某点度限制的MST
- POJ - 1639 最小限制生成树
- poj 1639 有限制的最小生成树
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)