CSU 1116 Kingdoms(枚举最小生成树)

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1116

解题报告:一个国家有n个城市,有m条路可以修,修每条路要一定的金币,现在这个国家只有K个金币,每个城市有一些人,要你求怎么修路使得总的费用在K的范围内,同时使得跟首都连接的城市的人口(包括首都的人口)要最多,问最多的人口是多少。

枚举连接哪些城市,然后分别构造最小生成树。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn = 20;
 7 int pop[maxn],mat[maxn][maxn];
 8 int T,n,m,k;
 9
10 int prim(int d,int& ans)
11 {
12     int visit[maxn],f = 1;
13     memset(visit,0,sizeof(visit));
14     d = (d << 1) + 1;
15     for(int i = 1;i <= n;++i)
16     {
17         visit[i] = d & 1;
18         d >>= 1;
19     }
20     int tot = 0;
21     visit[1] = 2;   //等于2才是在集合中的
22     while(1)
23     {
24         int l = -1,temp = 0x7fffffff;
25         for(int i = 1;i <= n;++i)
26         if(visit[i] == 2)
27         {
28             for(int j = 1;j <= n;++j)
29             if(visit[j] == 1 && mat[i][j] < temp)
30             {
31                 l = j;
32                 temp = mat[i][j];
33             }
34         }
35         if(l == -1 || temp > 100000) break;
36         tot += temp;
37         visit[l] = 2;
38     }
39     ans = 0;
40     for(int i = 1;i <= n;++i)
41     if(visit[i] == 2)
42     ans += pop[i];
43     return tot;
44 }
45
46 int main()
47 {
48     scanf("%d",&T);
49     while(T--)
50     {
51         scanf("%d%d%d",&n,&m,&k);
52         for(int i = 1;i <= n;++i)
53         scanf("%d",&pop[i]);
54         int x,y,z;
55         memset(mat,0x3f,sizeof(mat));
56         while(m--)
57         {
58             scanf("%d%d%d",&x,&y,&z);
59             mat[x][y] = mat[y][x] = min(mat[x][y],z);
60         }
61         int tot = 0,t;
62         for(int i = 0;i <= (1 << (n-1))-1;++i)
63         {
64             int temp = prim(i,t);
65             if(temp <= k) tot = max(tot,t);
66         }
67         printf("%d\n",tot);
68     }
69     return 0;
70 }

时间: 2024-10-20 00:19:57

CSU 1116 Kingdoms(枚举最小生成树)的相关文章

CSU 1116 Kingdoms 最小生成树(prim)

由于点数只有16,而点1又必选,暴力枚举选点情况,每次做一个最小生成树 这里用的prim算法,要注意的是存在选取这些点但找不到生成树的情况,需要将之排出 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<map> using namespace std; const int INF=0x3f3f3f3f; const int max

CSU 1116 Kingdoms

传送门 Description A kingdom has n cities numbered 1 to n, and some bidirectional roads connecting cities. The capital is always city 1. After a war, all the roads of the kingdom are destroyed. The king wants to rebuild some of the roads to connect the

csuoj 1116: Kingdoms

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1116 1116: Kingdoms Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 293  Solved: 82[Submit][Status][Web Board] Description A kingdom has n cities numbered 1 to n, and some bidirectional roads connecting

hdu 2489 Minimal Ratio Tree(dfs枚举 + 最小生成树)~~~

题目: 链接:点击打开链接 题意: 输入n个点,要求选m个点满足连接m个点的m-1条边权值和sum与点的权值和ans使得sum/ans最小,并输出所选的m个点,如果有多种情况就选第一个点最小的,如果第一个点也相同就选第二个点最小的........ 思路: 求一个图中的一颗子树,使得Sum(edge weight)/Sum(point weight)最小~ 数据量小,暴力枚举~~~~~dfs暴力枚举C(M,N)种情况. 枚举出这M个点之后,Sum(point weight)固定,进行prim或者K

UVA1395 Slim Span(枚举最小生成树)

题意: 求最小生成树中,最大的边减去最小的边 最小值. 看了题解发现真简单=_= 将每条边进行从小到大排序,然后从最小到大一次枚举最小生成树,当构成生成树的时候,更新最小值 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int INF = 0x3f3f3f3f; 7 con

hdu 2489 Minimal Ratio Tree 枚举+最小生成树

点的总数很小,直接枚举就好. #include <stdio.h> #include <string.h> #define N 20 #define inf 1000000 int mk[N],n,k,ans[N]; double low[N],val[N]; double map[N][N],MIN; double prim() { int i,j; double sum=0; double tot=0; for(i=1;i<=n;i++) low[i]=inf; int

HDU 2489 Minimal Ratio Tree (DFS枚举+最小生成树Prim)

Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is calculated according to the following equation. Given a complete graph of n nodes with all nodes and edges weighted, your task is to find a tree, which is a su

hdu1598 find the most comfortable road 枚举+最小生成树

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define MAXN 210 5 #define INF 2147483646 6 using namespace std; 7 8 int f[MAXN], Rank[MAXN]; //Rank长度 9 int n, m, pos; 10 11 struct Edge{ 12 int u, v, val; 13 //按照val从小到大排列

csu1116 Kingdoms 最小生成树-枚举状态

题目链接: csu 1116 题意: 有一幅双向图连接N个城市(标号1~n,1表示首都)  每个城市有一个价值W. 地震摧毁了所有道路,现给出可修复的m条道路并给出修复每条道路所需的费用 问在总费用不超过k的情况下,使得  与  首都连通的所有城市  的价值和 最大 解题思路: 点的数量不超过16 ,2^16次方枚举所有城市是否在连通的集合类 再通过kruskal判断这个集合是否合法即可 代码: #include<iostream> #include<cstdio> #includ