1.POJ - 1251 Junle Roads
题目分析:
最小生成树模板题,求将所有点连通的最小代价
题目代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 30, M = N * N;
int n;
int p[N];
struct node
{
int a, b, c;
bool operator<(const node& e) const
{
return c < e.c;
}
}edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int main()
{
while (cin >> n, n)
{
int cnt = 0;
for (int i = 1; i < n; i++)
{
char a, b;
int c, num;
cin >> a >> num;
for (int j = 1; j <= num; j++)
{
cin >> b >> c;
edge[cnt].a = a - 'A', edge[cnt].b = b - 'A', edge[cnt].c = c;
cnt++;
}
}
sort(edge, edge + cnt);
for (int i = 0; i < N; i++)
p[i] = i;
int ans = 0;
for (int i = 0; i < cnt; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
int w = edge[i].c;
if (fa != fb)
{
ans += w;
p[fa] = fb;
}
}
cout << ans << endl;
}
return 0;
}
2.POJ - 1287 Networking
题目链接:
题目分析:
这一题和第一题做法相同,甚至建图比第一题还容易
题目分析:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100, M = N * N;
int n, m;
int p[N];
struct node
{
int a, b, c;
bool operator<(const node& e) const
{
return c < e.c;
}
}edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int main()
{
while (cin >> n, n)
{
cin >> m;
for (int i = 1; i <= m; i++)
{
cin >> edge[i].a >> edge[i].b >> edge[i].c;
}
sort(edge + 1, edge + 1 + m);
for (int i = 1; i <= n; i++)
p[i] = i;
int ans = 0;
for (int i = 1; i <= m; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
int w = edge[i].c;
if (fa != fb)
{
ans += w;
p[fa] = fb;
}
}
cout << ans << endl;
}
}
3.POJ - 2031 Building a Space Station
题目链接:
题目分析:
最小生成树。需要注意的是,建边的时候边长为max(0,两球圆心的距离-两个球的半径之和)
题目代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 110, M = N * N;
int n;
int p[N];
struct nodes
{
int a, b;
double c;
bool operator<(const nodes& e) const
{
return c < e.c;
}
}edge[M];
struct node
{
double x, y, z, r;
}v[N];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
double cal(struct node a, struct node b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
double dz = a.z - b.z;
return sqrt(dx * dx + dy * dy + dz * dz);
}
int main()
{
while (cin >> n, n)
{
for (int i = 1; i <= n; i++)
{
cin >> v[i].x >> v[i].y >> v[i].z >> v[i].r;
}
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
double dis = max(0.0, cal(v[i], v[j]) - (v[i].r + v[j].r));
edge[cnt].a = i, edge[cnt].b = j, edge[cnt].c = dis;
cnt++;
}
}
sort(edge, edge + cnt);
for (int i = 1; i <= n; i++)
p[i] = i;
double ans = 0;
for (int i = 0; i < cnt; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
double w = edge[i].c;
if (fa != fb)
{
ans += w;
p[fa] = fb;
}
}
printf("%.3lf\n", ans);
}
}
4.Constructing Roads
题目链接:
题目分析:
最小生成树,需要注意的是:题目中给定的必须修的路必须先合并
不懂为什么的可以看本题的样例,因为1到2的路是一定要修的,所以我们只需要管2到3的路,因此答案为179
如果我们按照正常顺序,那么先修的是2到3,总费用为179,接下来为1到3,总费用为179+692>179,最后修1到2
题目代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef pair<int, int>PII;
const int N = 110, M = N * N;
int n, m;
int p[N];
map<PII, int>mp;
struct node
{
int a, b, c;
bool operator<(const node& e) const
{
return c < e.c;
}
}edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int main()
{
cin >> n;
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
int w;
cin >> w;
edge[cnt].a = i, edge[cnt].b = j, edge[cnt].c = w;
cnt++;
}
}
sort(edge, edge + cnt);
for (int i = 1; i < N; i++)
p[i] = i;
cin >> m;
while (m--)
{
int a, b;
cin >> a >> b;
if (find(a) != find(b))
p[find(a)] = find(b);
}
int ans = 0;
for (int i = 1; i <= cnt; i++)
{
int a = edge[i].a, fa = find(a);
int b = edge[i].b, fb = find(b);
int w = edge[i].c;
if (fa != fb)
{
ans += w;
p[fa] = fb;
}
}
cout << ans;
}
5.QS Network
题目链接:
题目分析:
每次建边所需的费用为边权加上两个点的点权,再跑kruscal
题目代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1010, M = N * N;
int p[N], a[N];
int n;
struct node
{
int a, b, c;
bool operator<(const node& e) const
{
return c < e.c;
}
}edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
void solve()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
edge[cnt].a = i, edge[cnt].b = j;
cin >> edge[cnt].c;
edge[cnt].c += a[i] + a[j];
cnt++;
}
}
sort(edge, edge + cnt);
for (int i = 1; i <= n; i++) p[i] = i;
int ans = 0;
for (int i = 0; i < cnt; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
int w = edge[i].c;
if (fa != fb)
{
ans += w;
p[fa] = fb;
}
}
cout << ans << endl;
}
int main()
{
int T = 1;
cin >> T;
while (T--) solve();
return 0;
}
6.Truck History
题目链接:
题目分析:
任意两个字符串之间的花费为对应位置不同字符的个数,暴力枚举点对然后建边,因为是无向图,所以只需要枚举上三角矩阵或者下三角矩阵即可
题目代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 5010, M = N * N;
int p[N], a[N];
string str[N];
int n;
struct node
{
int a, b, c;
bool operator<(const node& e) const
{
return c < e.c;
}
}edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
while (cin >> n, n)
{
for (int i = 1; i <= n; i++) cin >> str[i];
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
int w = 0;
for (int k = 0; k < 7; k++)
{
if (str[i][k] != str[j][k])
w++;
}
edge[cnt].a = i, edge[cnt].b = j, edge[cnt].c = w;
cnt++;
}
}
sort(edge, edge + cnt);
for (int i = 1; i <= n; i++) p[i] = i;
int ans = 0;
for (int i = 0; i < cnt; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
int w = edge[i].c;
if (fa != fb)
{
ans += w;
p[fa] = fb;
}
}
printf("The highest possible quality is 1/%d\n", ans);
}
return 0;
}
7.Arctic Network
题目链接:
题目分析:
题目代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<double, double>PDD;
const int N = 600, M = N * N;
int n, m;
int p[N];
PDD v[N];
struct node
{
int a, b;
double c;
bool operator<(const node& e) const
{
return c < e.c;
}
}edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
double cal(PDD a, PDD b)
{
double dx = a.first - b.first;
double dy = a.second - b.second;
return sqrt(dx * dx + dy * dy);
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> v[i].first >> v[i].second;
}
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
double dist = cal(v[i], v[j]);
edge[cnt].a = i, edge[cnt].b = j, edge[cnt++].c = dist;
}
}
sort(edge, edge + cnt);
for (int i = 1; i <= n; i++)
p[i] = i;
int res = n;
double ans = 0;
for (int i = 0; i < cnt; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
double w = edge[i].c;
if (res <= m)
break;
if (fa != fb)
{
res--;
p[fa] = fb;
ans = w;
}
}
printf("%.2lf\n", ans);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--) solve();
return 0;
}
8.Highways
题目链接:
题目分析:
kruscal算法中,已经有的道路优先合并,否则可能会对结果产生影响,类似于第四题
题目代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<double, double>PDD;
const int N = 800, M = N * N;
int n, m;
int p[N];
PDD v[N];
struct node
{
int a, b;
double c;
bool operator<(const node& e) const
{
return c < e.c;
}
}edge[M];
double cal(PDD a, PDD b)
{
double dx = a.first - b.first;
double dy = a.second - b.second;
return sqrt(dx * dx + dy * dy);
}
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> v[i].first >> v[i].second;
}
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
double dist = cal(v[i], v[j]);
edge[cnt].a = i, edge[cnt].b = j, edge[cnt++].c = dist;
}
}
sort(edge, edge + cnt);
for (int i = 1; i <= n; i++)
p[i] = i;
cin >> m;
while (m--)
{
int a, b;
cin >> a >> b;
int fa = find(a),fb = find(b);
if (fa != fb)
p[fa] = fb;
}
for (int i = 0; i < cnt; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
if (fa != fb)
{
cout << edge[i].a << ' ' << edge[i].b << endl;
p[fa] = fb;
}
}
return 0;
}
9.Agri-Net
题目链接:
题目分析:
模板题
题目代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110, M = N * N;
int p[N];
int n;
struct node
{
int a, b, c;
bool operator<(const node &e) const
{
return c < e.c;
}
} edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
while(cin>>n)
{
int cnt=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
edge[cnt].a=i,edge[cnt].b=j;
cin>>edge[cnt].c;
cnt++;
}
}
sort(edge,edge+cnt);
for(int i=1;i<=n;i++)
p[i]=i;
int ans=0;
for(int i=0;i<cnt;i++)
{
int fa=find(edge[i].a);
int fb=find(edge[i].b);
int w=edge[i].c;
if(fa!=fb)
{
ans+=w;
p[fa]=fb;
}
}
cout<<ans<<endl;
}
}
10.Borg Maze
题目链接:
题目分析:
题目代码
12.还是畅通工程
题目链接:
题目分析:
模板题,注意边的数量
题目代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110, M = N * N;
int n, p[N];
struct node
{
int a, b, c;
bool operator<(const node &e) const
{
return c < e.c;
}
} edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
while (cin >> n, n)
{
for (int i = 1; i <= n * (n - 1) / 2; i++)
{
cin >> edge[i].a >> edge[i].b >> edge[i].c;
}
sort(edge + 1, edge + 1 + n * (n - 1) / 2);
for (int i = 1; i <= n; i++)
p[i] = i;
int ans = 0;
for (int i = 1; i <= n * (n - 1) / 2; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
int w = edge[i].c;
if (fa != fb)
{
ans += w;
p[fa] = fb;
}
}
cout << ans << endl;
}
}
13.Jungle Roads
题目链接:
与第一题一样
题目分析:
略
题目代码:
略
14.畅通工程再续
题目链接:
题目分析:
只将距离在10~1000之间的边进行kruscal,本题还要判断最后是否能让所有点都连通,根据kruscal算法,一开始有n个集合,每次合并集合数量减一,如果最后只有一个集合,那么就是连通的,否则不连通
题目代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<double, double> PII;
const int N = 110, M = N * N;
int n, p[N];
PII v[N];
struct node
{
int a, b;
double c;
bool operator<(const node &e) const
{
return c < e.c;
}
} edge[M];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
double cal(PII a, PII b)
{
double dx = a.first - b.first;
double dy = a.second - b.second;
return sqrt(dx * dx + dy * dy);
}
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
v[i] = make_pair(x, y);
}
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
double dist = cal(v[i], v[j]);
if (dist >= 10 && dist <= 1000)
{
edge[cnt].a = i, edge[cnt].b = j, edge[cnt].c = dist * 100;
cnt++;
}
}
}
sort(edge, edge + cnt);
for (int i = 1; i <= n; i++)
p[i] = i;
double ans = 0;
int res = n;
for (int i = 0; i < cnt; i++)
{
int fa = find(edge[i].a);
int fb = find(edge[i].b);
double w = edge[i].c;
if (fa != fb)
{
ans += w;
res--;
p[fa] = fb;
}
}
if (res == 1)
printf("%.1lf\n", ans);
else
printf("oh!\n");
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}