最小生成树和最短路
- 题目列表
-
- A Jungle Roads(POJ1251)
- B Networking(POJ1287)
- C Building a Space Station(POJ2031)
- D Constructing Roads(POJ2421)
- E Truck History(POJ1789)
- F Arctic Network(POJ2349)
- G Highways(POJ1751)
- H Til the Cows Come Home(POJ2387)
- I Frogger(POJ2253)
- J Heavy Transportation(POJ1797)
- K Silver Cow Party(POJ3268)
- L Currency Exchange(POJ1860)
- M Wormholes(POJ3259)
- N MPI Maelstrom(POJ1502)
- O Cow Contest(POJ3660)
- P Arbitrage (POJ2240)
- 总结
题目列表
A Jungle Roads(POJ1251)
最小生成树板子题,直接套板子就能过。
AC代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int max_n = 1e5;
int parent[max_n];
int myRank[max_n];
void init(int n)
{
for (int i = 0; i < n; i++)
{
parent[i] = i;
myRank[i] = 0;
}
}
int find(int x)
{
if (x != parent[x])
parent[x] = find(parent[x]);
return parent[x];
}
void unite(int x, int y)
{
x = find(x);
y = find(y);
if (x == y)
return;
if (myRank[x] < myRank[y])
{
parent[x] = y;
}
else
{
parent[y] = x;
if (myRank[x] == myRank[y])
{
myRank[x]++;
}
}
}
bool same(int x, int y)
{
return find(x) == find(y);
}
struct edge
{
int stN, edN, cost;
bool operator<(edge e1)
{
return this->cost < e1.cost;
}
} edges[max_n];
int krukal(int v, int e)
{
sort(edges, edges + e);
init(v);
int res = 0;
int nedge = 0;
for (int i = 0; i < e && nedge != v - 1; i++)
{
edge et = edges[i];
if (!same(et.stN, et.edN))
{
unite(et.stN, et.edN);
res += et.cost;
nedge++;
}
}
if (nedge < v - 1)
res = -1;
return res;
}
int main()
{
int n, index;
while (cin >> n)
{
if (n == 0)
break;
cin >> index;
for (int i = 0; i < index; i++)
cin >> edges[i].stN >> edges[i].edN >> edges[i].cost;
int ans = krukal(n, index);
cout << ans << endl;
}
return 0;
}
B Networking(POJ1287)
还是板子题,没有什么需要注意的地方。
AC代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int max_n = 1e5;
int parent[max_n];
void init(int n)
{
for (int i = 0; i < n + 10; i++)
parent[i] = i;
}
int find(int x)
{
if (x != parent[x])
parent[x] = find(parent[x]);
return parent[x];
}
void unite(int x, int y)
{
x = find(x);
y = find(y);
if (x == y)
return;
parent[x] = y;
}
bool same(int x, int y)
{
return find(x) == find(y);
}
struct edge
{
int stN, edN, cost;
bool operator<(edge e1)
{
return this->cost < e1.cost;
}
} edges[max_n];
int krukal(int v, int e)
{
sort(edges, edges + e);
init(v);
int res = 0;
int nedge = 0;
for (int i = 0; i < e && nedge != v - 1; i++)
{
edge et = edges[i];
if (!same(et.stN, et.edN))
{
unite(et.stN, et.edN);
res += et.cost;
nedge++;
}
}
if (nedge < v - 1) //不连通
res = -1;
return res;
}
int main()
{
//点数 边数
int n, index;
while (cin >> n)
{
if (n == 0)
break;
cin >> index;
for (int i = 0; i < index; i++)
cin >> edges[i].stN >> edges[i].edN >> edges[i].cost;
int ans = krukal(n, index);
cout << ans << endl;
}
return 0;
}
C Building a Space Station(POJ2031)
题目大意:
求对立体中求得最小生成树。
思路:
先处理出来边,两个球如果相交了那么代表这条边得权值为0。然后求所有边得最小生成树就行了。
AC代码
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int max_n = 1e4;
struct pp
{
int index;
double x, y, z, r;
};
double cost(pp p1, pp p2)
{
double ans = sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y) + (p2.z - p1.z) * (p2.z - p1.z)) - (p1.r + p2.r);
return ans > 0 ? ans : 0;
}
int parent[max_n];
vector<pp> vp;
struct edge
{
int stN, edN;
double co;
bool operator<(edge e)
{
return co - e.co < 0;
}
} edges[max_n];
void init(int n)
{
for (int i = 0; i < n; i++)
parent[i] = i;
}
int find(int x)
{
if (x != parent[x])
parent[x] = find(parent[x]);
return parent[x];
}
void unit(int x, int y)
{
x = find(x);
y = find(y);
if (x == y)
return;
parent[x] = y;
}
bool same(int x, int y)
{
return find(x) == find(y);
}
int main()
{
int n;
while (cin >> n)
{
if (n == 0)
break;
vp.clear();
for (int i = 0; i < n; i++)
{
pp tmp;
cin >> tmp.x >> tmp.y >> tmp.z >> tmp.r;
tmp.index = i;
vp.push_back(tmp);
}
int index = 0;
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
edges[index].stN = vp[i].index;
edges[index].edN = vp[j].index;
edges[index].co = cost(vp[i], vp[j]);
index++;
}
}
init(n);
sort(edges, edges + index);
double res = 0;
int nedge = 0;
for (int i = 0; i < index && nedge != n - 1; i++)
{
edge e = edges[i];
if (!same(e.stN, e.edN))
{
unit(e.stN, e.edN);
res += e.co;
nedge++;
}
}
printf("%.3lf\n", res);
}
return 0;
}
D Constructing Roads(POJ2421)
题目大意:
给你一个邻接矩阵并且已知某些点已经连接好了,求最小生成树。
思路:
已经连好的点可以直接加入到并查集里面或者将 权值设为零。
AC代码
#include <iostream>
#include <algorithm>
using namespace std;
int arr[200][