非正规做法,一个一个的暴,减一下枝,还得采用sort,qsort居然过不了……

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. #define LL long long
  7.  
  8. struct node{
  9. int u, v, no;
  10. LL dis;
  11. };
  12.  
  13. int n, len, pos, p[1010], num[1010][2];
  14. double maxx;
  15. node v[500010], cnt[1010];
  16.  
  17. LL dist(int i, int j){
  18. return (LL)(num[i][0] - num[j][0]) * (num[i][0] - num[j][0]) + (LL)(num[i][1] - num[j][1]) * (num[i][1] - num[j][1]);
  19. }
  20.  
  21. bool cmp(const node &p1, const node &p2) {
  22. return p1.dis < p2.dis;
  23. }
  24.  
  25. int find(int x) {
  26. return p[x] == x ? x : p[x] = find(p[x]);
  27. }
  28.  
  29. void Kruskal(){
  30. sort(v, v + len, cmp);
  31. maxx = 0;
  32. pos = 0;
  33. int k = n - 1;
  34. for(int i = 0; i < n; ++i) p[i] = i;
  35. for(int i = 0; i < len; ++i){
  36. int x = find(v[i].u);
  37. int y = find(v[i].v);
  38. if(x!=y){
  39. maxx += sqrt((double)v[i].dis);
  40. p[x] = y;
  41. cnt[pos] = v[i];
  42. cnt[pos++].no = i;
  43. --k;
  44. if(!k) break;
  45. }
  46. }
  47. }
  48.  
  49. void solve(){
  50. double t = maxx;
  51. for(int k = 0; k < pos; ++k){
  52. if(!cnt[k].u) continue;
  53. double e = t - sqrt((double)cnt[k].dis);
  54. for(int i = 0; i < n; ++i) p[i] = i;
  55. for(int i = 0; i < pos; ++i)
  56. if(i != k){
  57. int x = find(cnt[i].u);
  58. int y = find(cnt[i].v);
  59. p[x] = y;
  60. }
  61. for(int i = cnt[k].no + 1; i < len; ++i){
  62. int x1 = find(v[i].u);
  63. int y1 = find(v[i].v);
  64. if(x1 != y1){
  65. e += sqrt((double)v[i].dis);
  66. if(maxx < e) maxx = e;
  67. break;
  68. }
  69. }
  70. }
  71. }
  72.  
  73. int main()
  74. {
  75. //freopen("in.txt", "r", stdin);
  76. int t, k;
  77. scanf("%d", &t);
  78. while(t--){
  79. scanf("%d %d", &n, &k);
  80. for(int i = 0; i < n; ++i)
  81. scanf("%d %d", &num[i][0], &num[i][1]);
  82. len = 0;
  83. for(int i = 0; i < n; ++i)
  84. for(int j = i+1; j < n; ++j){
  85. v[len].dis = dist(i, j);
  86. v[len].u = i;
  87. v[len++].v = j;
  88. }
  89. Kruskal();
  90. solve();
  91. printf("%.2lf\n", maxx * k);
  92. }
  93. return 0;
  94. }
  95.  
  96. 第二次做:用dfs+并查集,速度果然提高了许多
  97.  
  98. #include <cstdio>
  99. #include <cmath>
  100. #include <cstdlib>
  101. #include <algorithm>
  102. using namespace std;
  103. #define LL long long
  104.  
  105. struct node{
  106. int u, v;
  107. LL dis;
  108. };
  109.  
  110. int n, len, pos, p[1010], num[1010][2], head[1010], next[2010][3];
  111. double maxx, cnt;
  112. node v[500010];
  113.  
  114. LL dist(int i, int j){
  115. return (LL)(num[i][0] - num[j][0]) * (num[i][0] - num[j][0]) + (LL)(num[i][1] - num[j][1]) * (num[i][1] - num[j][1]);
  116. }
  117.  
  118. bool cmp(const node &p1, const node &p2) {
  119. return p1.dis < p2.dis;
  120. }
  121.  
  122. int find(int x) {
  123. return p[x] == x ? x : p[x] = find(p[x]);
  124. }
  125.  
  126. void add(int u, int v, int i){
  127. next[pos][1] = v;
  128. next[pos][2] = i;
  129. next[pos][0] = head[u];
  130. head[u] = pos++;
  131. }
  132.  
  133. void Kruskal(){
  134. sort(v, v + len, cmp);
  135. maxx = 0;
  136. pos = 0;
  137. int k = n - 1;
  138. for(int i = 0; i < n; ++i) p[i] = i;
  139. for(int i = 0; i < len; ++i){
  140. int x = find(v[i].u);
  141. int y = find(v[i].v);
  142. if(x!=y){
  143. maxx += sqrt((double)v[i].dis);
  144. p[x] = y;
  145. add(v[i].u, v[i].v, i);
  146. add(v[i].v, v[i].u, i);
  147. --k;
  148. if(!k) break;
  149. }
  150. }
  151. }
  152.  
  153. void dfs(int cur, int fa){
  154. for(int i = head[cur]; i != -1; i = next[i][0]){
  155. int u = next[i][1];
  156. int no = next[i][2];
  157. if(u != fa){
  158. dfs(u, cur);
  159. int x = find(cur);
  160. int y = find(u);
  161. if(u && cur){
  162. double t = maxx - sqrt(double(v[no].dis));
  163. for(int j = no + 1; j < len; ++j){
  164. int x1 = find(v[j].u);
  165. int y1 = find(v[j].v);
  166. if(x1 != y1 && (x1 == y || y1 == y)){
  167. cnt = max(cnt, t + sqrt(double(v[j].dis)));
  168. break;
  169. }
  170. }
  171. }
  172. p[x] = y;
  173. }
  174. }
  175. }
  176.  
  177. int main()
  178. {
  179. // freopen("in.txt", "r", stdin);
  180. int t, k;
  181. scanf("%d", &t);
  182. while(t--){
  183. scanf("%d %d", &n, &k);
  184. for(int i = 0; i < n; ++i)
  185. scanf("%d %d", &num[i][0], &num[i][1]), head[i] = -1;
  186. len = 0;
  187. for(int i = 0; i < n; ++i)
  188. for(int j = i+1; j < n; ++j){
  189. v[len].dis = dist(i, j);
  190. v[len].u = i;
  191. v[len++].v = j;
  192. }
  193. Kruskal();
  194. for(int i = 0; i < n; ++i) p[i] = i;
  195. cnt = maxx;
  196. dfs(0, -1);
  197. printf("%.2lf\n", cnt * k);
  198. }
  199. return 0;
  200. }
  201.  
  202. 第三次做:采用普里姆算法,果然快了很多,适用于稠密图,也就是边比较多的图,N^2的算法,网上大多数采用普里姆算法+树形dp,我是采用普里姆算法然后dfs优化做的,c++也照样过
  203. #include <cstdio>
  204. #include <cmath>
  205. #include <cstdlib>
  206. #include <algorithm>
  207. using namespace std;
  208. #define LL long long
  209. LL inf = 10000000000000000LL;
  210.  
  211. int n, dfs_cnt, p[1010], num[1010][2], head[1010], next[2010][2];
  212. double maxx, q;
  213. bool flag;
  214. LL v[1005][1005], cnt[1010], arr[1005][1005];
  215.  
  216. LL dist(int i, int j)
  217. {
  218. return (LL)(num[i][0] - num[j][0]) * (num[i][0] - num[j][0]) + (LL)(num[i][1] - num[j][1]) * (num[i][1] - num[j][1]);
  219. }
  220.  
  221. void add(int u, int v){
  222. next[dfs_cnt][1] = v;
  223. next[dfs_cnt][0] = head[u];
  224. head[u] = dfs_cnt++;
  225. }
  226.  
  227. void prim()
  228. {
  229. maxx = 0, dfs_cnt = 0;
  230. for(int i = 1; i < n; ++i){
  231. cnt[i] = v[0][i];
  232. p[i] = 0;
  233. }
  234. cnt[0] = 0, p[0] = 0;
  235. for(int i = 1; i < n; ++i){
  236. int k = 0;
  237. LL c = inf;
  238. for(int j = 1; j < n; ++j)
  239. if(cnt[j] != 0 && cnt[j] < c){
  240. c = cnt[j];
  241. k = j;
  242. }
  243. add(p[k], k);
  244. add(k, p[k]);
  245. maxx += sqrt(double(c));
  246. cnt[k] = 0;
  247. for(int j = 1; j < n; ++j)
  248. if(cnt[j] != 0 && v[k][j] < cnt[j]){
  249. cnt[j] = v[k][j];
  250. p[j] = k;
  251. }
  252. }
  253. }
  254.  
  255. double tarjan(int cur, int fa, int pos, LL f){
  256. double c = inf;
  257. for(int i = head[cur]; i != -1; i = next[i][0]){
  258. int u = next[i][1];
  259. if(u != fa){
  260. c = min(c, tarjan(u, cur, pos, f));
  261. if(arr[u][pos] != f) c = min(c, sqrt(double(arr[u][pos])) - sqrt(double(f)));
  262. else if(flag) c = min(c, 0.0);
  263. else flag = 1;
  264. //printf("%.2lf ", c);
  265. }
  266. }
  267. return c;
  268. }
  269.  
  270. void dfs(int cur, int fa){
  271. for(int i = head[cur]; i != -1; i = next[i][0]){
  272. int u = next[i][1];
  273. if(u != fa){
  274. dfs(u, cur);
  275. if(u && cur){
  276. double c = inf;
  277. for(int j = 0; j < n; ++j)
  278. if(j != cur)
  279. c = min(c, sqrt(double(v[u][j])) - sqrt(double(v[u][cur])));
  280. flag = 0;
  281. if(arr[u][cur] == v[u][cur]) flag = 1;
  282. else c = min(c, sqrt(double(arr[u][cur])));
  283. c = min(c, tarjan(u, cur, cur, v[u][cur]));
  284. maxx = max(maxx, q + c);
  285. }
  286. v[u][cur] = v[cur][u] = inf;
  287. for(int j = 0; j < n; ++j)
  288. if(v[cur][j] == inf || v[u][j] == inf) v[cur][j] = inf;
  289. else v[cur][j] = min(v[cur][j], v[u][j]);
  290. }
  291. }
  292. }
  293.  
  294. int main()
  295. {
  296. // freopen("in.txt", "r", stdin);
  297. int t, k;
  298. scanf("%d", &t);
  299. while(t--){
  300. scanf("%d %d", &n, &k);
  301. for(int i = 0; i < n; ++i)
  302. scanf("%d %d", &num[i][0], &num[i][1]), head[i] = -1;
  303. for(int i = 0; i < n; ++i){
  304. arr[i][i] = v[i][i] = inf;
  305. for(int j = i + 1; j < n; ++j)
  306. if(i != j) arr[i][j] = arr[j][i] = v[i][j] = v[j][i] = dist(i, j);
  307. }
  308. prim();
  309. q = maxx;
  310. dfs(0, -1);
  311. printf("%.2lf\n", maxx * k);
  312. }
  313. return 0;
  314. }

hdu 4756 Install Air Conditioning的更多相关文章

  1. HDU 4756 Install Air Conditioning(次小生成树)

    题目大意:给你n个点然后让你求出去掉一条边之后所形成的最小生成树. 比較基础的次小生成树吧. ..先prime一遍求出最小生成树.在dfs求出次小生成树. Install Air Conditioni ...

  2. HDU 4756 Install Air Conditioning (MST+树形DP)

    题意:n-1个宿舍,1个供电站,n个位置每两个位置都有边相连,其中有一条边不能连,求n个位置连通的最小花费的最大值. 析:因为要连通,还要权值最小,所以就是MST了,然后就是改变一条边,然后去找出改变 ...

  3. Install Air Conditioning HDU - 4756(最小生成树+树形dp)

    Install Air Conditioning HDU - 4756 题意是要让n-1间宿舍和发电站相连 也就是连通嘛 最小生成树板子一套 但是还有个限制条件 就是其中有两个宿舍是不能连着的 要求所 ...

  4. hdu4756 Install Air Conditioning(MST + 树形DP)

    题目请戳这里 题目大意:给n个点,现在要使这n个点连通,并且要求代价最小.现在有2个点之间不能直接连通(除了第一个点),求最小代价. 题目分析:跟这题一样样的,唉,又是原题..先求mst,然后枚举边, ...

  5. MST(prim)+树形dp-hdu-4756-Install Air Conditioning

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4756 题目意思: n-1个宿舍,1个供电站,n个位置每两个位置都有边相连,其中有一条边不能连,求n个 ...

  6. 每日英语:Can Going In and Out of Air Conditioning Cause Colds?

    For most people, summer involves numerous daily shifts between scorching outdoor heat and frosty air ...

  7. hdu 4756 MST+树形dp ****

    题意:给你n(n = 1000)个二维点,第一个点是power plant,还有n - 1个点是dormitories.然后现在知道有一条寝室到寝室的边是不能连的,但是我们不知道是哪条边,问这种情况下 ...

  8. 【转载】ACM总结——dp专辑

    感谢博主——      http://blog.csdn.net/cc_again?viewmode=list       ----------  Accagain  2014年5月15日 动态规划一 ...

  9. 【DP专辑】ACM动态规划总结

    转载请注明出处,谢谢.   http://blog.csdn.net/cc_again?viewmode=list          ----------  Accagain  2014年5月15日 ...

随机推荐

  1. mysql存储过程、函数和触发器的创建 [转]

    http://blog.itpub.net/559237/viewspace-438942/ 今天花了半天时间来研究mysql的存储过程函数和触发器的创建,觉得和oracle的大同小异,只是语法上更艰 ...

  2. [RxJS] Refactoring CombineLatest to WithLatestFrom

    This lesson shows why it’s preferable to using withLatestFrom instead of combineLatest in certain sc ...

  3. VS2010调试小技巧

    在VS下做开发的时候我们进行调试的时候路径是这个样子的:http://localhost:端口号/项目名称/index.aspx 但是发布到服务器上面的时候却是这个样子的:http://www.xxx ...

  4. 怎么样学好C++

    声明:这篇文章非本人所写,转自:http://coolshell.cn/articles/4119.html 昨天写了一篇如何学好C语言,就有人回复问我如何学好C++,所以,我把我个人的一些学习经验写 ...

  5. 重学《C#高级编程》(序)

    小生码农一枚,以前只是看别人写博客,从来没有想过要自己写博文,突然之间“脑抽”想自己也写点什么,遂在博客园开通这个博客. 简单介绍下自己吧,本人90后,父母对我没有大的想法,只是希望我平安成长,多学习 ...

  6. Lesson 2: Dive Into Typography (排版)

    Lesson 2: Dive Into Typography (排版) 排版是字的艺术,是关于字的一切:字体.字号.行高.行长.字重(斜体/加粗/正常).字距(kerning).行距(leading) ...

  7. 活动指示器UIActivityIndicatorView

    活动指示器UIActivityIndicatorView可以告知用户有一个操作正在进行中 1.创建    UIActivityIndicatorView *activityIndicatorView ...

  8. FileStream 操作文件复制

    static void Main(string[] args) { string source = @"D:\c\集合.avi"; string target = @"C ...

  9. StringBuilder 大量字符串时使用,速度比较快

    public static void Main(string[] args) { Stopwatch sw = new Stopwatch(); //程序计时器 StringBuilder str = ...

  10. 用ThreadLocal管理事务

    1.适用场景 一个service,操作两个dao,要求两个dao为同一个事务,要么全成功,要么全失败.