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

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define LL long long struct node{
int u, v, no;
LL dis;
}; int n, len, pos, p[1010], num[1010][2];
double maxx;
node v[500010], cnt[1010]; LL dist(int i, int j){
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]);
} bool cmp(const node &p1, const node &p2) {
return p1.dis < p2.dis;
} int find(int x) {
return p[x] == x ? x : p[x] = find(p[x]);
} void Kruskal(){
sort(v, v + len, cmp);
maxx = 0;
pos = 0;
int k = n - 1;
for(int i = 0; i < n; ++i) p[i] = i;
for(int i = 0; i < len; ++i){
int x = find(v[i].u);
int y = find(v[i].v);
if(x!=y){
maxx += sqrt((double)v[i].dis);
p[x] = y;
cnt[pos] = v[i];
cnt[pos++].no = i;
--k;
if(!k) break;
}
}
} void solve(){
double t = maxx;
for(int k = 0; k < pos; ++k){
if(!cnt[k].u) continue;
double e = t - sqrt((double)cnt[k].dis);
for(int i = 0; i < n; ++i) p[i] = i;
for(int i = 0; i < pos; ++i)
if(i != k){
int x = find(cnt[i].u);
int y = find(cnt[i].v);
p[x] = y;
}
for(int i = cnt[k].no + 1; i < len; ++i){
int x1 = find(v[i].u);
int y1 = find(v[i].v);
if(x1 != y1){
e += sqrt((double)v[i].dis);
if(maxx < e) maxx = e;
break;
}
}
}
} int main()
{
//freopen("in.txt", "r", stdin);
int t, k;
scanf("%d", &t);
while(t--){
scanf("%d %d", &n, &k);
for(int i = 0; i < n; ++i)
scanf("%d %d", &num[i][0], &num[i][1]);
len = 0;
for(int i = 0; i < n; ++i)
for(int j = i+1; j < n; ++j){
v[len].dis = dist(i, j);
v[len].u = i;
v[len++].v = j;
}
Kruskal();
solve();
printf("%.2lf\n", maxx * k);
}
return 0;
} 第二次做:用dfs+并查集,速度果然提高了许多 #include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define LL long long struct node{
int u, v;
LL dis;
}; int n, len, pos, p[1010], num[1010][2], head[1010], next[2010][3];
double maxx, cnt;
node v[500010]; LL dist(int i, int j){
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]);
} bool cmp(const node &p1, const node &p2) {
return p1.dis < p2.dis;
} int find(int x) {
return p[x] == x ? x : p[x] = find(p[x]);
} void add(int u, int v, int i){
next[pos][1] = v;
next[pos][2] = i;
next[pos][0] = head[u];
head[u] = pos++;
} void Kruskal(){
sort(v, v + len, cmp);
maxx = 0;
pos = 0;
int k = n - 1;
for(int i = 0; i < n; ++i) p[i] = i;
for(int i = 0; i < len; ++i){
int x = find(v[i].u);
int y = find(v[i].v);
if(x!=y){
maxx += sqrt((double)v[i].dis);
p[x] = y;
add(v[i].u, v[i].v, i);
add(v[i].v, v[i].u, i);
--k;
if(!k) break;
}
}
} void dfs(int cur, int fa){
for(int i = head[cur]; i != -1; i = next[i][0]){
int u = next[i][1];
int no = next[i][2];
if(u != fa){
dfs(u, cur);
int x = find(cur);
int y = find(u);
if(u && cur){
double t = maxx - sqrt(double(v[no].dis));
for(int j = no + 1; j < len; ++j){
int x1 = find(v[j].u);
int y1 = find(v[j].v);
if(x1 != y1 && (x1 == y || y1 == y)){
cnt = max(cnt, t + sqrt(double(v[j].dis)));
break;
}
}
}
p[x] = y;
}
}
} int main()
{
// freopen("in.txt", "r", stdin);
int t, k;
scanf("%d", &t);
while(t--){
scanf("%d %d", &n, &k);
for(int i = 0; i < n; ++i)
scanf("%d %d", &num[i][0], &num[i][1]), head[i] = -1;
len = 0;
for(int i = 0; i < n; ++i)
for(int j = i+1; j < n; ++j){
v[len].dis = dist(i, j);
v[len].u = i;
v[len++].v = j;
}
Kruskal();
for(int i = 0; i < n; ++i) p[i] = i;
cnt = maxx;
dfs(0, -1);
printf("%.2lf\n", cnt * k);
}
return 0;
} 第三次做:采用普里姆算法,果然快了很多,适用于稠密图,也就是边比较多的图,N^2的算法,网上大多数采用普里姆算法+树形dp,我是采用普里姆算法然后dfs优化做的,c++也照样过
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define LL long long
LL inf = 10000000000000000LL; int n, dfs_cnt, p[1010], num[1010][2], head[1010], next[2010][2];
double maxx, q;
bool flag;
LL v[1005][1005], cnt[1010], arr[1005][1005]; LL dist(int i, int j)
{
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]);
} void add(int u, int v){
next[dfs_cnt][1] = v;
next[dfs_cnt][0] = head[u];
head[u] = dfs_cnt++;
} void prim()
{
maxx = 0, dfs_cnt = 0;
for(int i = 1; i < n; ++i){
cnt[i] = v[0][i];
p[i] = 0;
}
cnt[0] = 0, p[0] = 0;
for(int i = 1; i < n; ++i){
int k = 0;
LL c = inf;
for(int j = 1; j < n; ++j)
if(cnt[j] != 0 && cnt[j] < c){
c = cnt[j];
k = j;
}
add(p[k], k);
add(k, p[k]);
maxx += sqrt(double(c));
cnt[k] = 0;
for(int j = 1; j < n; ++j)
if(cnt[j] != 0 && v[k][j] < cnt[j]){
cnt[j] = v[k][j];
p[j] = k;
}
}
} double tarjan(int cur, int fa, int pos, LL f){
double c = inf;
for(int i = head[cur]; i != -1; i = next[i][0]){
int u = next[i][1];
if(u != fa){
c = min(c, tarjan(u, cur, pos, f));
if(arr[u][pos] != f) c = min(c, sqrt(double(arr[u][pos])) - sqrt(double(f)));
else if(flag) c = min(c, 0.0);
else flag = 1;
//printf("%.2lf ", c);
}
}
return c;
} void dfs(int cur, int fa){
for(int i = head[cur]; i != -1; i = next[i][0]){
int u = next[i][1];
if(u != fa){
dfs(u, cur);
if(u && cur){
double c = inf;
for(int j = 0; j < n; ++j)
if(j != cur)
c = min(c, sqrt(double(v[u][j])) - sqrt(double(v[u][cur])));
flag = 0;
if(arr[u][cur] == v[u][cur]) flag = 1;
else c = min(c, sqrt(double(arr[u][cur])));
c = min(c, tarjan(u, cur, cur, v[u][cur]));
maxx = max(maxx, q + c);
}
v[u][cur] = v[cur][u] = inf;
for(int j = 0; j < n; ++j)
if(v[cur][j] == inf || v[u][j] == inf) v[cur][j] = inf;
else v[cur][j] = min(v[cur][j], v[u][j]);
}
}
} int main()
{
// freopen("in.txt", "r", stdin);
int t, k;
scanf("%d", &t);
while(t--){
scanf("%d %d", &n, &k);
for(int i = 0; i < n; ++i)
scanf("%d %d", &num[i][0], &num[i][1]), head[i] = -1;
for(int i = 0; i < n; ++i){
arr[i][i] = v[i][i] = inf;
for(int j = i + 1; j < n; ++j)
if(i != j) arr[i][j] = arr[j][i] = v[i][j] = v[j][i] = dist(i, j);
}
prim();
q = maxx;
dfs(0, -1);
printf("%.2lf\n", maxx * k);
}
return 0;
}

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. Multi-touch.

    TP(Multi-touch). 1.Win7有6个版本,分别如下. Windows 7 Starter (初级版)                                        不支 ...

  2. linux系统自动执行任务(转)

    开机启动 开机启动应该是我们很经常的需求了,我们常需要在开机时就自动执行某些命令来开启服务,进程等,有了它我们不必再在每次开机时输入同一堆命令. chkconfig命令 使用chkconfig命令可以 ...

  3. openwrt interface

    orige : http://www.cnblogs.com/preorder69/p/3959187.html 这篇算是对openwrt网络接口的一个翻译吧,源地址:http://wiki.open ...

  4. rhel Linux 网络配置

    --网络配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 1)DHCPDEVICE=eth0BOOTPROTO=dhcpONBOOT=yes2)静态IP  ...

  5. 【转】MVP和MVC的区别

    转自:http://www.cnblogs.com/end/archive/2011/06/02/2068512.html MVC和MVP到底有什么区别呢? 从这幅图可以看到,我们可以看到在MVC里, ...

  6. 使用vs中的工具进行架构比较

    使用vs自带的架构比较工具可以对不同库中的结构进行比较,也可以将源中的架构更新到目标架构中.当然这种更新只是架构的更新,数据并不会同步.

  7. 腾讯RTX登录提示失败问题及处理办法

    出现问题时图片: 解决步骤: 首先ping一下RTX管理器所在的的ip地址 telnet一下服务器的端口 8000,8010 是否能通. 具体操作: 在无法登陆的客户端电脑上开始-运行-输入cmd 确 ...

  8. Dom4j 添加 / 更新 / 删除 XML

    1.获得文档 /** *1.获得解析流 *2.解析XML */ 2.添加 /** *1.获取父元素 *2.创建元素 *3.创建属性并添加到元素中 *4.元素添加到根节点 */ 3.更新 /** *1. ...

  9. Java系列--第三篇 基于Maven的Android开发CAIO

    学习要打好基础,这里用一个项目来学习一下Android的组件,参考网址为这个但不限于这个.有些东西的学习,理解三遍理论还不如一遍操作,所谓理论来自实践,实践是检验真理的唯一标准.所以,虽然看懂了那篇文 ...

  10. UCOS 信号量

    uCOS-II信号量OSSemCreate(0)和OSSemCreate(1)详解 (2014-04-22 18:04:18) 转载▼ 标签: it 分类: 操作系统 在ucos-II中,为了实现任务 ...