zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", maxx * k);
        }
        return 0;
    }


  • 相关阅读:
    【转】随机函数的rand、srand用法
    realloc,malloc,calloc函数的区别
    c语言中time相关函数
    C语言strdup函数
    c语言strtod()函数的用法
    (转)从拜占庭将军问题谈谈为什么pow是目前最好的共识机制
    Linux命令行编辑快捷键
    少走弯路的10条忠告
    centos6下升级git版本的操作记录
    (转)Ctrl+H 浪潮Raid配置文档
  • 原文地址:https://www.cnblogs.com/pangblog/p/3341793.html
Copyright © 2011-2022 走看看