• hdu 2489(枚举 + 最小生成树)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2489

    思路:由于N, M的范围比较少,直接枚举所有的可能情况,然后求MST判断即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    
    const int MAX_N = 17;
    const double eps = 1e-10;
    struct Edge {
    	int u, v, w;
    	Edge() {}
    	Edge(int _u, int _v, int _w) : u(_u), v(_v), w(_w) {}
    } edge[MAX_N * MAX_N];
    
    int cmp(const Edge &e1, const Edge &e2) 
    {
    	return e1.w < e2.w;
    }
    
    int N, M, cnt, weight[MAX_N], g[MAX_N][MAX_N];
    int parent[MAX_N];
    void Init()
    {
    	for (int i = 0; i < N; ++i) parent[i] = i;
    }
    
    int find(int x)
    {
    	if (x == parent[x]) return x;
    
    	return parent[x] = find(parent[x]);
    }
    
    void Union(int u, int v)
    {
    	int r1 = find(u), r2 = find(v);
    	if (r1 == r2) return;
    
    	parent[r1] = r2;
    }
    
    double res;
    vector<int > tmp, ans;
    bool vis[MAX_N];
    void gao(int state)
    {
    	tmp.clear();
    	memset(vis, false, sizeof(vis));
    	int a = 0, b = 0;
    	for (int i = 0; i < N; ++i) {
    		if ((1 << i) & state) tmp.push_back(i), b += weight[i], vis[i] = true;
    	}
    
    	Init();
    	for (int i = 0; i < cnt; ++i) {
    		Edge e = edge[i];
    		if (vis[e.u] && vis[e.v]) {
    			if (find(e.u) != find(e.v)) {
    				Union(e.u, e.v);
    				a += e.w;
    			}
    		}
    	}
    
    	if (res < eps) {
    		res = a * 1.0 / b;
    		ans = tmp;
    	} else if (a * 1.0 / b + eps < res) {
    		res = a * 1.0 / b;
    		ans = tmp;
    	} else if (fabs(a * 1.0 / b - res) < eps) {
    		bool tag = false;
    		for (int i = 0; i < (int)ans.size(); ++i) {
    			if (ans[i] > tmp[i]) { tag = true; break; }
    		}
    		
    		if (tag) ans = tmp;
    	}
    	
    }
    
    int main()
    {
    	while (~scanf("%d %d", &N, &M)) {
    		if (N == 0 && M == 0) break;
    
    		for (int i = 0; i < N; ++i) scanf("%d", &weight[i]);
    		for (int i = 0; i < N; ++i) {
    			for (int j = 0; j < N; ++j) scanf("%d", &g[i][j]);
    		}
    		
    		cnt = 0;
    		for (int i = 0; i < N; ++i) {
    			for (int j = i + 1; j < N; ++j) edge[cnt++] = Edge(i, j, g[i][j]);
    		}
    
    		sort(edge, edge + cnt, cmp);
    		res = 0.0;
    		ans.clear();
    		for (int s = 0; s < (1 << N); ++s) {
    			int x = s, n = 0;
    			while (x) {
    				++n;
    				x &= (x - 1);
    			}
    			
    			if (n == M) {
    				gao(s);
    			}
    		}
    
    		for (int i = 0; i < (int)ans.size(); ++i) {
    			printf(i == 0 ? "%d" : " %d", ans[i] + 1);
    		}
    		puts("");
    		
    	}
    	return 0;
    }
    


  • 相关阅读:
    java加密解密用法
    进程和线程
    office使用技巧
    apktool+dex2jar+jd_gui
    shell编程学习
    编程常犯的错误
    编程语言学习清单
    使用github托管自己的项目
    c# 异常 的 异想
    DNLA自学(一) UPnP设备发现
  • 原文地址:https://www.cnblogs.com/wally/p/4477052.html
Copyright © 2020-2023  润新知