hdu 4756 Install Air Conditioning

非正规做法,一个一个的暴,减一下枝,还得采用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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值