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:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <map> 6 #define MAX_N 35 7 #define MAX_M 905 8 #define INF 1000000000 9 10 using namespace std; 11 12 struct Edge 13 { 14 int s; 15 int t; 16 int len; 17 Edge(int _s,int _t,int _len) 18 { 19 s=_s; 20 t=_t; 21 len=_len; 22 } 23 Edge(){} 24 friend bool operator < (const Edge &a,const Edge &b) 25 { 26 return a.len<b.len; 27 } 28 }; 29 30 int n=0,m,k; 31 int ans=0,deg=0; 32 int par[MAX_N]; 33 int lnk[MAX_N]; 34 int minn[MAX_N]; 35 int a[MAX_N][MAX_N]; 36 bool flag[MAX_N][MAX_N]; 37 Edge dp[MAX_N]; 38 Edge edge[MAX_M]; 39 map<string,int> mp; 40 41 int cal_id(const string &s) 42 { 43 if(mp.count(s)>0) return mp[s]; 44 mp.insert(pair<string,int>(s,++n)); 45 return n; 46 } 47 48 void read() 49 { 50 cin>>m; 51 string s1,s2; 52 int v; 53 memset(a,-1,sizeof(a)); 54 cal_id("Park"); 55 for(int i=0;i<m;i++) 56 { 57 cin>>s1>>s2>>v; 58 int id1=cal_id(s1); 59 int id2=cal_id(s2); 60 edge[i]=Edge(id1,id2,v); 61 if(a[id1][id2]==-1) a[id1][id2]=a[id2][id1]=v; 62 else a[id1][id2]=a[id2][id1]=min(a[id1][id2],v); 63 } 64 cin>>k; 65 } 66 67 void init_union_find() 68 { 69 for(int i=1;i<=n;i++) 70 { 71 par[i]=i; 72 } 73 } 74 75 int find(int x) 76 { 77 return par[x]==x ? x : par[x]=find(par[x]); 78 } 79 80 void unite(int x,int y) 81 { 82 int px=find(x); 83 int py=find(y); 84 if(px==py) return; 85 par[px]=py; 86 } 87 88 bool same(int x,int y) 89 { 90 return find(x)==find(y); 91 } 92 93 void kruskal() 94 { 95 init_union_find(); 96 sort(edge,edge+m); 97 memset(flag,false,sizeof(flag)); 98 for(int i=0;i<m;i++) 99 { 100 Edge temp=edge[i]; 101 if(temp.s==1 || temp.t==1) continue; 102 if(!same(temp.s,temp.t)) 103 { 104 ans+=temp.len; 105 unite(temp.s,temp.t); 106 flag[temp.s][temp.t]=flag[temp.t][temp.s]=true; 107 } 108 } 109 } 110 111 void cal_mdeg() 112 { 113 memset(minn,0x3f,sizeof(minn)); 114 for(int i=2;i<=n;i++) 115 { 116 if(a[1][i]!=-1) 117 { 118 int p=find(i); 119 if(a[1][i]<minn[p]) 120 { 121 minn[p]=a[1][i]; 122 lnk[p]=i; 123 } 124 } 125 } 126 for(int i=2;i<=n;i++) 127 { 128 if(minn[i]<INF) 129 { 130 deg++; 131 ans+=minn[i]; 132 flag[1][lnk[i]]=flag[lnk[i]][1]=true; 133 } 134 } 135 } 136 137 void dfs(int x,int p) 138 { 139 for(int i=1;i<=n;i++) 140 { 141 if(flag[x][i] && i!=p) 142 { 143 if(dp[i].len==-1) 144 { 145 if(a[x][i]>dp[x].len) dp[i]=Edge(x,i,a[x][i]); 146 else dp[i]=dp[x]; 147 } 148 dfs(i,x); 149 } 150 } 151 } 152 153 void cal_kdeg() 154 { 155 for(int j=deg+1;j<=k;j++) 156 { 157 dp[1]=Edge(-1,-1,-INF); 158 for(int i=2;i<=n;i++) 159 { 160 if(flag[1][i]) dp[i]=Edge(-1,-1,-INF); 161 else dp[i]=Edge(-1,-1,-1); 162 } 163 dfs(1,-1); 164 int dst,maxn=-INF; 165 for(int i=2;i<=n;i++) 166 { 167 if(a[1][i]!=-1 && dp[i].len-a[1][i]>maxn) 168 { 169 maxn=dp[i].len-a[1][i]; 170 dst=i; 171 } 172 } 173 if(maxn<=0) return; 174 int x=dp[dst].s,y=dp[dst].t; 175 flag[x][y]=flag[y][x]=false; 176 flag[1][dst]=flag[dst][1]=true; 177 ans-=maxn; 178 } 179 } 180 181 void solve() 182 { 183 kruskal(); 184 cal_mdeg(); 185 cal_kdeg(); 186 } 187 188 void print() 189 { 190 cout<<"Total miles driven: "<<ans<<endl; 191 } 192 193 int main() 194 { 195 read(); 196 solve(); 197 print(); 198 }
转载于:https://www.cnblogs.com/Leohh/p/8082522.html
POJ 1639 Picnic Planning:最小度限制生成树相关推荐
- pku 1639 Picnic Planning 最小度限制生成树
http://poj.org/problem?id=1639 题意: 见黑书. 思路: 最小限制树模板题: #include <iostream> #include <cstdio& ...
- 【题解】poj1639[2018.8.24校赛 最小生成树 A]Picnic Planning 最小度限制生成树
题目链接 Description The Contortion Brothers are a famous set of circus clowns, known worldwide for thei ...
- poj1639 Picnic Planning 最小度数限制生成树
题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...
- 次小生成树 最小度限制生成树
首先说明这是一个坑! 因为发现啊次小生成树为什不用树链剖分写(虽然麻烦但是思路各种清晰!),最小度限制生成树可以用lct写(而且是似乎要比那个直接写的算法容易因为要各种建边删边dfs(就没有考虑过时间 ...
- 洛谷P5633 最小度限制生成树 题解
洛谷P5633 最小度限制生成树 题解 题目链接:P5633 最小度限制生成树 题意: 给你一个有 n n n 个节点, m m m 条边的带权无向图,你需要求得一个生成树,使边权总和最小,且满足编号 ...
- Picnic Planning POJ - 1639(度限制生成树)
解题报告 题意理解 给定一张N个点,M个边的无向图,求出无向图的一颗最小生成树,但是我们要求一号节点的入度不可以超过给定的整数S 也就是一个最小生成树,要求它的一号节点,最多只能和S个节点相连. 思路 ...
- Poj·Picnic Planning
初见安~这里是传送门:Poj P1639 Description The Contortion Brothers are a famous set of circus clowns, known wo ...
- 【POJ】2377 Bad Cowtractors(最大生成树)
简单题,模板题 求解最大生成树,提交一直WA,感觉没有什么问题啊,就是在求解最小生成树的模板基础上稍加修改即可,后来发现在输出a,b,c给map二维数组的时候还必须有判断条件,略为有点坑,因为之前做的 ...
- poj 2728 Desert King(最小比率生成树 / 0-1分数规划 / 二分)
二分答案,我们要找最小的答案,如果有更小的答案说明 ∑W−Z∗∑L<=0∑W−Z∗∑L <= 0∑W−Z∗∑L<=0. #include<cstdio> #include ...
最新文章
- 复旦大学自然语言处理实验室发布模型鲁棒性评测平台TextFlint
- 机器学习和深度学习学习资料
- Unity3D获取Andorid设备返回键,主页键等功能
- 如何使用 Node 后端创建 React 应用程序:完整指南
- Unity3D 动态加载 图片序列正反播放
- libjpeg(1)
- 从两个模型带你了解DAOS 分布式异步对象存储
- 用程序去掉文件和文件夹的只读属性
- 黑马程序员 re模块的高级用法 学习笔记
- 最雷视频集合贴:优酷啊优酷啊
- 代理模式———动态代理
- 分布式数据库中间件—TDDL的使用介绍
- 什么是发动机号,发动机号码是什么?
- 微软的SqlHelper做数据层(一)
- 开机出现RUNDLL加载:C:WINDOWS\downlo~1\Cnsmin.dll时…
- 三、Linux文件颜色代表意义
- 移动互联网创业者遭遇巨头模仿蚕食
- 根据订单号查询并复制一行
- 3款大数据bi工具,让企业数据分析更简单
- 盛大无传奇 啥时离职成见面招呼语