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;

}


 

 

你可能感兴趣的:(Condition)