一、刷题题解
1、# 无线通讯网
## 题目描述
国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;
每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。
任意两个配备了一条卫星电话线路的哨所(两边都ᤕ有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 $D$,这是受收发器的功率限制。收发器的功率越高,通话距离 $D$ 会更远,但同时价格也会更贵。
收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个 $D$。你的任务是确定收发器必须的最小通话距离 $D$,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。
## 输入格式
从 wireless.in 中输入数据第 1 行,2 个整数 $S$ 和 $P$,$S$ 表示可安装的卫星电话的哨所数,$P$ 表示边防哨所的数量。接下里 $P$ 行,每行两个整数 $x,y$ 描述一个哨所的平面坐标 $(x, y)$,以 km 为单位。
## 输出格式
输出 wireless.out 中
第 1 行,1 个实数 $D$,表示无线电收发器的最小传输距离,精确到小数点后两位。
## 样例 #1
### 样例输入 #1
```
2 4
0 100
0 300
0 600
150 750
```
### 样例输出 #1
```
212.13
```
## 提示
对于 $20\%$ 的数据:$P = 2,S = 1$
对于另外 $20\%$ 的数据:$P = 4,S = 2$
对于 $100\%$ 的数据保证:$1 ≤ S ≤ 100$,$S < P ≤ 500$,$0 ≤ x,y ≤ 10000$。
这题可以用kruskal算法;
但是,需要注意的是卫星电话,当我们已选边>=n-s时结束;
同时我们需要自己计算所有对节点的距离;
比如3个点就有3条边,现在有两个卫星电话,我们只需要1条最短的边,就可用kruskal算法选;
附代码
#include<bits/stdc++.h>
using namespace std;
long long x[1005],y[1005],fq[1005],zs;
long double zx=0;
int bs;
struct nod
{
int X,Y;
long double w;
}q[1000005];
bool bj(nod i,nod j)
{
return i.w<j.w;
}
long double js(long long i,long long j)
{ long long X=x[i]-x[j],Y=y[i]-y[j];
return (long double)sqrt((long double)X*X+Y*Y);
}
int find(int i)
{
if(fq[i]==i)return i;
return fq[i]=find(fq[i]);
}
void join(int a,int b)
{
if(find(a)==find(b))
return;
fq[find(a)]=b;
}
int main()
{
long long s,n;
cin>>s>>n;
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i],fq[i]=i;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{q[++zs].X=i;q[zs].Y=j;q[zs].w=js(i,j);}
sort(q+1,q+zs+1,bj);
for(int i=1;i<=zs;i++)
if(find(q[i].X)!=find(q[i].Y))
{
join(q[i].X,q[i].Y);
bs++;
if(bs>=n-s)
{printf("%.2Lf",q[i].w);break;}
}
return 0;
}
2、# 【模板】单源最短路径(弱化版)
## 题目背景
本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 [P4779](https://www.luogu.org/problemnew/show/P4779)。
## 题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
## 输入格式
第一行包含三个整数 $n,m,s$,分别表示点的个数、有向边的个数、出发点的编号。
接下来 $m$ 行每行包含三个整数 $u,v,w$,表示一条 $u \to v$ 的,长度为 $w$ 的边。
## 输出格式
输出一行 $n$ 个整数,第 $i$ 个表示 $s$ 到第 $i$ 个点的最短路径,若不能到达则输出 $2^{31}-1$。
## 样例 #1
### 样例输入 #1
```
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
```
### 样例输出 #1
```
0 2 4 3
```
## 提示
【数据范围】
对于 $20\%$ 的数据:$1\le n \le 5$,$1\le m \le 15$;
对于 $40\%$ 的数据:$1\le n \le 100$,$1\le m \le 10^4$;
对于 $70\%$ 的数据:$1\le n \le 1000$,$1\le m \le 10^5$;
对于 $100\%$ 的数据:$1 \le n \le 10^4$,$1\le m \le 5\times 10^5$,$1\le u,v\le n$,$w\ge 0$,$\sum w< 2^{31}$,保证数据随机。
**Update 2022/07/29:两个点之间可能有多条边,敬请注意。**
对于真正 $100\%$ 的数据,请移步 [P4779](https://www.luogu.org/problemnew/show/P4779)。请注意,该题与本题数据范围略有不同。
样例说明:
![](https://cdn.luogu.com.cn/upload/pic/7641.png)
图片1到3和1到4的文字位置调换
这题是要求1点到其他点的最短路径,由于数据量过大我用floyd时间超限,我就用Dijkstra+stl优先队列+链式前向星;
首先我们将点的关系通过链式前向星,存储,接着,将开始节点,入队列,距离赋值0;
然后,进入循环(直到队列为空结束),取出队列第一个,在删除队列top,在判断取出的节点是否已选中,没有则进入下级循环;
然后进行,取出相邻的节点+取出的距离,和原本的距离比小就改变它,在将其入队列,循环直到没有相邻节点;
接着重复循环3、4;
附代码
#include<bits/stdc++.h>
#include<math.h>
using namespace std;
int n,m,s;
priority_queue<int,vector<pair<int,int> >,greater<pair<int,int> > >q;
struct node
{
int last;
int to;
int qz;
}edge[500005];
int he;
int head[100005];
bool xz[100005];
int jl[100005];
void jr(int a,int b,int c)
{ he++;
edge[he].last=head[a];
edge[he].to=b;
edge[he].qz=c;
head[a]=he;
}
int main()
{
for(int i=0;i<100005;i++)jl[i]=pow(2,31)-1;
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
jr(a,b,c);
}
jl[s]=0;
q.push(make_pair(0,s));
while(!q.empty())
{
int dq=q.top().second;
q.pop();
if(xz[dq]==true)continue;
xz[dq]=true;
for(int i=head[dq];i;i=edge[i].last)
if(!xz[edge[i].to] && jl[edge[i].to]>jl[dq]+edge[i].qz)
{
jl[edge[i].to]=jl[dq]+edge[i].qz;
q.push(make_pair(jl[edge[i].to],edge[i].to));
}
}
for(int i=1;i<=n;i++)
cout<<jl[i]<<' ';
return 0;
}