随便说点:
博主正在刷kuangbin专题的题目,初学者,没接触过什么算法,刷题的初衷是备战蓝桥杯,后来发现了算法资料大多是针对acm的,挑选kuangbin专题入门也是如此,毕竟这样分类看起来比较有目的的刷题。
所以有的代码比较冗余,越往后面的题解代码变化越大,
代码的风格和算法思想也是在一步步的学习和进步,多多包容,互相借鉴。
建议做题顺序:
做最小生成树专题没最短路和并查集专题时那么吃力,题目难度有下降。所以把题解都整合在一篇博客里
最小生成树基础:1 2 4 5 6 9 12 14
最小生成树应用:10 3 8 7
这是我做完一遍之后觉得比较好的做题顺序,由易到难,相同类型题放在一起加深理解。
题解目录
-
-
- 1.POJ 1251 Jungle Roads
- 2.POJ 1287 Networking
- 3.POJ 2031 Building a Space Station
- 4.POJ 2421 Constructing Roads
- 5.ZOJ 1586 QS Network
- 6.POJ 1789 Truck History
- 7.POJ 2349 Arctic Network
- 8.POJ 1751 Highways
- 9.POJ 1258 Agri-Net
- 10.POJ 3026 Borg Maze
- 11.POJ 1679 The Unique MST(次小生成树,放生成树专题写)
- 12.HDU 1233 还是畅通工程
- 13.HDU 1301 Jungle Roads(与题目1重复)
- 14.HDU 1875 畅通工程再续
-
1.POJ 1251 Jungle Roads
把字符转化成整型,然后套用模板
//poj1251
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 28, INF = 0x3f3f3f3f;
int maps[N][N],visit[N];
int d[N];
int n;
int prim()
{
int ans = 0;
for (int i = 1; i < n; i++)
d[i] = maps[0][i];
d[0] = 0;
for (int i = 1; i < n; i++)
{
int t = -1;
for (int j = 1; j < n; j++)
{
if (!visit[j])
if (d[j] < d[t] || t == -1)
t = j;
}
visit[t] = 1;
ans += d[t];
for (int j = 1; j < n; j++)
if (!visit[j])
d[j] = min(d[j], maps[t][j]);
}
return ans;
}
int main()
{
while (~scanf("%d", &n),n)
{
memset(maps, 0x3f, sizeof(maps));
memset(visit, 0, sizeof(visit));
for (int i = 0; i < n-1; i++)
{
char u;
int t;
scanf(" %c %d", &u, &t);
while (t--)
{
char v;
int w;
scanf(" %c %d", &v,&w);
maps[i][v - 'A'] = w;
maps[v - 'A'][i] = w;
}
}
printf("%d\n", prim());
}
return 0;
}
2.POJ 1287 Networking
模板题
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 55, INF = 0x3f3f3f3f;
int maps[N][N],visit[N];
int d[N];
int n, m;
int prim()
{
int ans = 0;
for (int i = 2; i <= n; i++)
d[i] = maps[1][i];
d[1] = 0;
for (int i = 2; i <= n; i++)
{
int t = -1;
for (int j = 2; j <= n; j++)
{
if (!visit[j])
if (d[j] < d[t] || t == -1)
t = j;
}
visit[t] = 1;
ans += d[t];
for (int j = 2; j <= n; j++)
if (!visit[j])
d[j] = min(d[j], maps[t][j]);
}
return ans;
}
int main()
{
while (~scanf("%d%d", &n, &m), n)
{
memset(maps, 0x3f, sizeof(maps));
memset(visit, 0, sizeof(visit));
for (int i = 0; i < m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
if (w < maps[u][v]) {
maps[u][v] = w;
maps[v][u] = w;
}
}
printf("%d\n", prim());
}
return 0;
}
3.POJ 2031 Building a Space Station
prim,注意 若两圆心距离-半径之和< =0则两点权值设置为0
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 105;
const double INF = 1e15;
int visit[N];
double d[N];
int n,m;
struct node {
double x, y, z, r;
}maps[N];
double getDis(double x1, double y1,double z1, double x2, double y2, double z2 )
{
return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)+ (z1 - z2)*(z1 - z2));
}
double prim()
{
memset(visit, 0, sizeof(visit));
for (int i = 1; i <= n; i++)
d[i] = INF;
double ans = 0;
for (int i = 2; i <= n; i++) {
double len = getDis(maps[1].x, maps[1].y, maps[1].z, maps[i].x, maps[i].y, maps[i].z);
double r = maps[1].r+ maps[i].r;
if (r >= len) d[i] = 0;
else d[i] = len-r;
}
d[1] = 0;
for (int i = 2; i <= n; i++)
{
int t = -1;
for (int j = 2; j <= n; j++)
{
if (!visit[j])
if (d[t] > d[j]|| t == -1)
t = j;
}
visit[t] = 1;
ans += d[t];
for (int j = 2; j <= n; j++)
if (!visit[j]) {
double len = getDis(maps[t].x, maps[t].y, maps[t].z, maps[j].x, maps[j].y, maps[j].z);
double r = maps[t].r + maps[j].r;
if (r >= len)len = 0;
else len = len - r;
d[j] = min</