今天上午刷题,下午回顾了一下知识点。明天开始准备复习一下预备役的内容。
无线通讯网
题目描述
国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;
每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。
任意两个配备了一条卫星电话线路的哨所(两边都ᤕ有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 DD,这是受收发器的功率限制。收发器的功率越高,通话距离 DD 会更远,但同时价格也会更贵。
收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个 DD。你的任务是确定收发器必须的最小通话距离 DD,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。
输入格式
从 wireless.in 中输入数据第 1 行,2 个整数 SS 和 PP,SS 表示可安装的卫星电话的哨所数,PP 表示边防哨所的数量。接下里 PP 行,每行两个整数 x,yx,y 描述一个哨所的平面坐标 (x, y)(x,y),以 km 为单位。
输出格式
输出 wireless.out 中
第 1 行,1 个实数 DD,表示无线电收发器的最小传输距离,精确到小数点后两位。
输入输出样例
输入 #1复制
2 4 0 100 0 300 0 600 150 750
输出 #1复制
212.13
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e6 + 10;
int fa[maxn];
int n,m,cnt=0,ans=0;
double sum=0;
struct node {
int x,y;
double z;
}edge[maxn];
struct Node{
int x,y;
}e[maxn];
void add(int x, int y, double z) {
edge[++cnt].x =x;
edge[cnt].y = y;
edge[cnt].z = z;
}
bool cmp(node a,node b) {
return a.z < b.z;
}
int get(int x) {
return x == fa[x] ? x : fa[x] = get(fa[x]);
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i ++) {
scanf("%d%d",&e[i].x,&e[i].y);
}
for(int i = 1; i <= m; i ++) {
fa[i] = i;
}
for(int i=1;i<=m;i++){
for(int j=i+1;j<=m;j++){
double zz=sqrt((double)(e[i].x - e[j].x) * (e[i].x - e[j].x) + (double)(e[i].y - e[j].y) * (e[i].y - e[j].y));
add(i,j,zz);
}
}
sort(edge + 1,edge + 1 + cnt,cmp);
// 每次加入一条最短的边
for(int i = 1; i <= cnt; i ++) {
int x = get(edge[i].x);
int y = get(edge[i].y);
if(x == y) continue;
fa[y] = x;
sum = edge[i].z;
ans++;
if(ans>=m-n)break;
}
printf("%0.2f",sum);
return 0;
}
口袋的天空
题目背景
小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。
有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。
题目描述
给你云朵的个数 NN,再给你 MM 个关系,表示哪些云朵可以连在一起。
现在小杉要把所有云朵连成 KK 个棉花糖,一个棉花糖最少要用掉一朵云,小杉想知道他怎么连,花费的代价最小。
输入格式
第一行有三个数 N,M,KN,M,K。
接下来 MM 行每行三个数 X,Y,LX,Y,L,表示XX云和 YY 云可以通过 LL 的代价连在一起。
输出格式
对每组数据输出一行,仅有一个整数,表示最小的代价。
如果怎么连都连不出 KK 个棉花糖,请输出 No Answer
。
输入输出样例
输入 #1复制
3 1 2 1 2 1
输出 #1复制
1
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
struct node {
int x,y,z;
}edge[maxn];
bool cmp(node a,node b) {
return a.z < b.z;
}
int fa[maxn];
int n,m,p;
int u,v,w;
long long sum=0;
int get(int x) {
return x == fa[x] ? x : fa[x] = get(fa[x]);
}
int main(void) {
scanf("%d%d%d",&n,&m,&p);
for(int i = 1; i <= m; i ++) {
scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
}
for(int i = 1; i <= n; i ++) {
fa[i] = i;
}
sort(edge + 1,edge + 1 + m,cmp);
// 每次加入一条最短的边
int cnt=1;
int i = 1;
while(cnt<=n-p){
if(i>m){
puts("No Answer");
return 0;
}
int x = get(edge[i].x);
int y = get(edge[i].y);
if(x!=y){
fa[y] = x;
sum += edge[i].z;
cnt++;
}
i++;
}
cout<<sum;
return 0;
}
Building Roads S
题目描述
Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.
Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1..N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M ≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.
给定 nn 个点的坐标,第 ii 个点的坐标为 (x_i,y_i)(xi,yi),这 nn 个点编号为 11 到 nn。给定 mm 条边,第 ii 条边连接第 u_iui 个点和第 v_ivi 个点。现在要求你添加一些边,并且能使得任意一点都可以连通其他所有点。求添加的边的总长度的最小值。
输入格式
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Two space-separated integers: Xi and Yi
* Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.
第一行两个整数 n,mn,m 代表点数与边数。
接下来 nn 行每行两个整数 x_i,y_ixi,yi 代表第 ii 个点的坐标。
接下来 mm 行每行两个整数 u_i,v_iui,vi 代表第 ii 条边连接第 u_iui 个点和第 v_ivi 个点。
输出格式
* Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.
一行一个实数代表添加的边的最小长度,要求保留两位小数,为了避免误差, 请用 6464 位实型变量进行计算。
输入输出样例
输入 #1复制
4 1 1 1 3 1 2 3 4 3 1 4
输出 #1复制
4.00
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e6 + 10;
int fa[maxn];
int n,m,cnt=0,ans=0;
double sum=0;
struct node {
int x,y;
double z;
}edge[maxn];
struct Node{
int x,y;
}e[maxn];
void add(int x, int y, double z) {
edge[++cnt].x =x;
edge[cnt].y = y;
edge[cnt].z = z;
}
bool cmp(node a,node b) {
return a.z < b.z;
}
int get(int x) {
return x == fa[x] ? x : fa[x] = get(fa[x]);
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i ++) {
scanf("%d%d",&e[i].x,&e[i].y);
}
for(int i = 1; i <= n; i ++) {
fa[i] = i;
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
double zz=sqrt((double)(e[i].x - e[j].x) * (e[i].x - e[j].x) + (double)(e[i].y - e[j].y) * (e[i].y - e[j].y));
add(i,j,zz);
}
}
for(int i=1;i<=m;i++){
int xx,yy;
scanf("%d%d",&xx,&yy);
add(xx,yy,0.0);
}
sort(edge + 1,edge + 1 + cnt,cmp);
// 每次加入一条最短的边
for(int i = 1; i <= cnt; i ++) {
int x = get(edge[i].x);
int y = get(edge[i].y);
if(x == y) continue;
fa[y] = x;
sum += edge[i].z;
ans++;
if(ans==n-1)break;
}
printf("%0.2f",sum);
return 0;
}