湖南省第八届省赛,最小生成树Prim算法+利用二进制的状态枚举

来源:互联网 发布:淘宝脏辫接发视频教程 编辑:程序博客网 时间:2024/06/15 11:41

题目信息:http://blog.csdn.net/acm_cxq/article/details/52192026

题意:

n个城市1--n,有m座桥可以城市,编号为1的城市是皇宫。修建每座桥的费用为c,每个城市的人口为pi。总费用为k。

求从皇宫出发,修建桥连接尽可能多的城市,城市相互直接或者间接连接通向皇宫,使得跟皇宫相连的所有城市的人口数之和为最大值,且费用不超过k。(无向图)


思路:巧妙运用二进制保存所有城市的状态,n个城市,每个城市选或不选,有2^n种可能。

1代表选,0代表不选。(1号城市必须入选)

如n等于4时,4个城市。

那么 1<<4等于16种可能,

如1101,代表第1,3,4城市入选,第二个城市不选。

然后将选入的城市的编号保存在一个数组里面,用prim算法求得入选城市相连后的花费。

在所有状态中,找出总人口最多的那个状态。


代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn = 20;const int INF = 999999999;int n;//城市,编号1--n,1为皇帝宫int m;//可以修的路int cost;//最大花费int weight[maxn];//每个城市对应的人口数int graph[maxn][maxn];//修建两个城市间路的费用int city[maxn];//被选的城市int state;//状态int COST,temp;//被选的城市的总人数int pos;//被选的城市个数void init() {for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {graph[i][j] = INF;if(i==j) graph[i][j] = 0;}}}int prim(int n,int pos) {int mincost[maxn];bool used[maxn];for(int i=0; i<n; i++) {mincost[city[i]] = graph[city[i]][pos];used[city[i]] = false;}mincost[pos] = 0;int res = 0;while(true) {int v = -1;//从未被true的顶点中选取从已经选的点到其权值最小的顶点for(int u=0; u<n; u++) {if(!used[city[u]]&&(v==-1||mincost[city[u]]<mincost[city[v]])) v = u;}if(v==-1) break;//更新完了 used[city[v]] = true;res+=mincost[city[v]];if(res>cost) return -1;for(int u = 0; u<n; u++) {mincost[city[u]] = min(mincost[city[u]],graph[city[v]][city[u]]);}}return res;}int main() {int cases;cin>>cases;int a,b,c;while(cases--) {cin>>n>>m>>cost;memset(city,0,sizeof(city)); for(int i=1; i<=n; i++) {cin>>weight[i];}for(int i=0; i<m; i++) {cin>>a>>b>>c;graph[a][b] = graph[b][a] = min(graph[a][b],c);}state = 1<<n;//枚举2的n次方中可能性 COST = -1;for(int i = state-1; i>0; i--) {//第一个城市必须入选,不然就进入下一个状态if(!(i&1)) continue;//如果这些状态中第一个城市没有入选,那么直接跳过 pos = 0;temp = 0;for(int j=0; j<n; j++) {//判断哪些城市入选 if((i>>j)&1) {city[pos++] = j+1;//表示第j+1个城市入选temp += weight[j+1];//加上第j+1个城市的人口数}}int cost = prim(pos,city[0]);//以第一个城市到各个被选城市的最小花费 //如果总花费不大于给定的总价,选择总人数最多的方案 if(cost!=-1) {COST = max(COST,temp);if(i==state-1) break;//如果所有城市都入选,那人口总数必定是最大的!!!}}cout<<COST<<endl;}}



0 0
原创粉丝点击