导语

我们都知道,BFS的性质可以运用在边权为1的最短路求解中。

单源边权值为1的最短路(实在不行只能自己打一个模板了)

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N=110;
const int INF=0x3f3f3f3f;int h[N],e[N],ne[N],idx;
int n,m;
int dist[N];
bool st[N];
queue<int> q;void add(int a,int b){e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}//求编号为1的点到编号为2的点的最短距离,数据假设满足条件 int bfs(){q.push({1});st[1]=true;while(q.size()){int t=q.front();q.pop();if(t==2) break;for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(!st[j]&&dist[j]>dist[t]+1){dist[j]=dist[t]+1;st[j]=true;q.push(j);}}}if(dist[2]==INF) return -1;else return dist[2];
}int main(){cin>>n>>m;memset(dist,0x3f,sizeof dist);for(int i=0;i<m;i++){int x,y;cin>>x>>y; add(x,y); add(y,x);}cout<<bfs();return 0;
} 

重点不是这个。

这篇文章是想写一下BFS的变形。

BFS+拆点

无线网络

精简题干后:

有n个已经修好的站点,和m个可以修建的站点,每两个站点之间的距离小于r就可以相互通信,求在新修站点小于k个的情况下,第一个站点到第二个站点的最小距离。边权为1。

和导语中的模板对比,这里变化了什么?

1.存在一部分站点是可以选择的,只是选择的个数不超过k

2.边没有直接给出来,需要我们判断哪些点直接存在边

3.从第一点可以看出,到达第二个站点存在1~k中情况。引入dist[N][N],第二个参数代表这条路径需要新修的站点个数

拆点:

就是上文的第三点。

BFS可以放好多东西进去维护啊

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#define x first
#define y second
using namespace std;
const int N=220,M=N*N;typedef long long LL;
typedef pair<int,int> PII;
queue<PII> q;
int n,m,k,r;
int dist[N][N];
int h[N],e[M],ne[M],idx;struct V{int x,y;
}v[N];bool check(int i,int j){LL dx=v[i].x-v[j].x;LL dy=v[i].y-v[j].y;return dx*dx+dy*dy<=r*r;
}void add(int a,int b){e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}int bfs(){q.push({1,0});memset(dist,0x3f,sizeof dist);dist[1][0]=0;while(q.size()){PII t=q.front();q.pop();for(int i=h[t.x];i!=-1;i=ne[i]){int x=t.x,y=t.y;int j=e[i];if(j>n) y++;if(y<=k){if(dist[j][y]>dist[t.x][t.y]+1){dist[j][y]=dist[t.x][t.y]+1;q.push({j,y});}          }}}int res=1e8;for(int i=0;i<=k;i++){res=min(res,dist[2][i]);} return res-1;
}int main(){cin>>n>>m>>k>>r;memset(h,-1,sizeof h);for(int i=1;i<=n;i++) cin>>v[i].x>>v[i].y;for(int i=n+1;i<=n+m;i++) cin>>v[i].x>>v[i].y;for(int i=1;i<=n+m;i++){for(int j=i+1;j<=n+m;j++){if(check(i,j)){add(i,j);add(j,i);}}}cout<<bfs();return 0;
}

多源BFS

最优配餐

简言之:求多个点到一个点的最短路径的最小值。

想法:可以看成一个超级原点经过多个点到达目标点的最短路径,其中超级原点到多个点的边权都是0,所以在BFS中直接放入多个点就可以了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
const int N=1010;typedef long long LL;
typedef pair<int,int> PII;
bool g[N][N];
int dist[N][N];
int n,m,k,d;
queue<PII> q;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};struct Tar{int x,y,c;
}tar[N*N];void bfs(){while(q.size()){PII t=q.front();q.pop();for(int i=0;i<4;i++){int x=t.x+dx[i],y=t.y+dy[i];if(x<1||x>n||y<1||y>n||g[x][y]) continue;if(dist[x][y]>dist[t.x][t.y]+1){dist[x][y]=dist[t.x][t.y]+1;q.push({x,y});}}}
}int main(){scanf("%d%d%d%d",&n,&m,&k,&d);memset(dist,0x3f,sizeof dist);while(m--){int x,y;scanf("%d%d",&x,&y);dist[x][y]=0;q.push({x,y});}for(int i=0;i<k;i++)scanf("%d%d%d",&tar[i].x,&tar[i].y,&tar[i].c); while(d--){int x,y;scanf("%d%d",&x,&y);g[x][y]=true;}bfs();LL res=0;for(int i=0;i<k;i++){res+=dist[tar[i].x][tar[i].y]*tar[i].c;}printf("%lld",res);return 0;
}

一个简单数字排序引发的血案

数字排序

题干很简单,给定n个数,统计他们出现的次数,然后按照出现次数递减的顺序输出,如果出现次数相等,数字小的先输出。

做法也很简单,一个结构体一个自定义比较函数。

#include<iostream>
#include<algorithm>
using namespace std;const int N=1010;
int n,x;
//可以离散化,但我不会 struct Data{int id;int num;
};
struct Data data[N];
bool cmp(struct Data a,struct Data b){if(a.num!=b.num) return a.num>b.num;else return a.id<b.id;
}int main(){cin>>n;for(int i=0;i<n;i++){cin>>x;data[x].id=x;data[x].num++;}sort(data,data+N,cmp);int i=0;while(data[i].num!=0){cout<<data[i].id<<" "<<data[i].num<<endl;i++;}return 0;
}

可是lf说这道题是因为数据范围小,这种类似桶排序的东西才可以过的。一直叫着去写map+优先队列。(其实离散化也可以,但我不会)

现在抽空看一下吧。

总体思路就是使用map<int,int> mp,进行数字统计,然后将map里面的元素放入优先队列,优先队列里的比较函数是可以自定义的。问题就出在重写<上。

priority_queue<> q默认大根堆,比较函数模板为less,为什么使用less却是大根堆呢?

//大根堆默认是less,我们越小越靠右,从左端取出最大元素
//重写<,相当于自定义优先级。 

当我们在结构体中重写<时:

 bool operator< (const node& n) const{if(cnt==cnt) return num>n.num;else return cnt<n.cnt;}

不免会产生疑惑

需求:次数不同时,次数大的放前面;相同时,数字小的放前面。

这里的<就可以看成优先级的一种关系,它定义了哪一个元素的优先级小。很明显比较次数时,次数越小,优先级越小。数字时,数字越大优先级越小。

写到这里我们大概明白了,这里重写的不是什么普普通通的小于符号,而是优先级判定标准。

树的直径

概念:一棵树上最短路的最大值

两次dfs

找到任意一个点x距离它最远的点y,在从y点出发,找到离它最远的点,这两点之间的距离就是树的直径。

下面是y为直径一个端点的证明

大臣的旅费

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10,M=2e5+10;int n;
int h[N],e[M],ne[M],w[M],idx;
int dist[N]; void add(int a,int b,int c){e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}void dfs(int u,int father,int dis){dist[u]=dis;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j!=father){dfs(j,u,dis+w[i]);}}
} int main(){cin>>n;memset(h,-1,sizeof h);for(int i=1;i<n;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}dfs(1,-1,0);int r=1;for(int i=1;i<=n;i++)if(dist[i]>dist[r]){r=i;} dfs(r,-1,0);for(int i=1;i<=n;i++)if(dist[i]>dist[r]){r=i;}int m=dist[r];printf("%lld",m*10+m*(m+1ll)/2);return 0;
}

在交这份代码的时候我陷入了MLE,我一度以为这种模拟的方式比不上struct+vector,结果发现是自己的边开小了(双边)。加了个M就过了。

不过struct+vector不用在意这些细节,也不错。

网络延时

这道题也是树的直径。

我们已知根节点就是编号为1的点,就只需要找到的到根节点的最大和次大层数相加就可以啦。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=2e4+10;int n,m,ans=0;
int p[N];
int h[N],e[N],ne[N],idx; int dfs(int u){int d1=0,d2=0;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];int d=dfs(j);if(d>=d1){d2=d1;d1=d;}else if(d>d2) d2=d;}ans=max(ans,d1+d2);return d1+1;
}void add(int a,int b){e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}int main(){cin>>n>>m;memset(h,-1,sizeof h);for(int i=2;i<=n;i++){int x;cin>>x;add(x,i);}for(int i=n+1;i<=n+m;i++){int x;cin>>x;add(x,i);}dfs(1);cout<<ans;return 0;
}

写到这里,就不得不思考一下,为什么同样是数的直径,这道题可以这样写,推广一下呢?不能推广,也可以思考一下他的特殊性。

好像是不行的,特殊性:这里是一个树,故不存在环。就写这么多了,后续有空在补一下吧。图论真好玩

【樱花飘落的速度是每秒5厘米】相关推荐

  1. 【题目】一根长度为M厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为每秒1厘米。当两只蚂蚁对撞时,二者同时掉头(掉头时间忽略不计)。给出每只蚂蚁的初始位置和朝向,计算T秒后每只蚂蚁的位置

    文件名:[作业] 作者:〈漆黑〉 描述:〈 一根长度为M厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为每秒1厘米.当两只蚂蚁对撞时,二者同时掉头(掉头时间忽略不计).给出每只蚂蚁的初始 ...

  2. 一个简单的Python樱花飘落动画代码

    以下是一个简单的Python樱花飘落动画代码示例: import random import time# 定义控制台大小和颜色 WIDTH = 80 HEIGHT = 25 COLORS = ['\0 ...

  3. jq制作樱花飘落特效

    jq制作樱花飘落特效 今天看到一些网站有樱花飘落,雨滴,流星,孔明灯等在整个页面飘动的特效,经过查询资料自己也做了一个,分享给大家 思路: 1.创建一个樱花的元素即为樱花图片 2.产生的樱花图片不止一 ...

  4. HTML超好看樱花飘落404页面源码+带时间

    正文: HTML超好看樱花飘落404页面源码+带时间,上传服务器解压就行,新增: 樱花飘落,音乐播放器,随机一言. 程序: wwreg.lanzoui.com/i5Pll07ibafc 图片:

  5. 2023 樱花飘落官网单页HTML源码

    直接修改主文件即可,无加密无授权,测试非常好看,有樱花特效,自带背景音乐等 2023 樱花飘落官网单页HTML源码

  6. 收藏转载樱花飘落代码

    樱花飘落代码非常漂亮.无需添加图片 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> < ...

  7. 樱花飘落,3D效果,抖音热门樱花飘落html

    樱花飘落,3D效果,抖音热门樱花飘落html 总结 代码如下(示例): <!DOCTYPE html><html><head><title>樱花飘落&l ...

  8. HTML 樱花飘落界面效果

    1.效果图 2.代码如下: <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  9. 为博客添加樱花飘落的效果

    偶然看见别人博客中樱花飘落的效果,感觉很棒,于是我也给博客加上了樱花 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 新建 sakura.js 新建一个 sakura.js 文件 ...

最新文章

  1. px,em,rem,vh,vw,vmin,vmax的区别
  2. VIM中空格和TAB的替换 [转]
  3. vue2.0 通过v-html指令渲染的富文本无法修改样式的解决方案
  4. npm package.json文件中的依赖关系,devDependencies和peerDependencies之间有什么区别?
  5. Python 下载的九种方法
  6. “象征界”的奇观:刘天怜花鸟工笔作品印象
  7. python修炼第四天
  8. Python数据结构与算法(二)--timeit模块
  9. c语言设计通讯录管理程序,C语言程序的设计学生通讯录管理系统方案.docx
  10. Mac读写ntfs磁盘工具:Paragon NTFS for Mac
  11. 吞云吐雾,美国电子烟问题,内附FDA的一个隐情
  12. linux系统网卡驱动更新,更新Linux网卡驱动
  13. 重庆财经职业学院计算机一级考试题,2021年重庆财经职业学院单招语文考试模拟试题库...
  14. Sidetree协议
  15. 谷歌地图开发:地理编码和反地理编码
  16. 移动端浏览器隐私模式/无痕模式使用本地存储localStorage/sessionStorage的问题
  17. 微信小程序对接快递鸟接口返回格式有误的解决
  18. 陈果《好的爱情》读书笔记
  19. 新郑计算机培训机构排名前十,新郑美术培训中心排名
  20. 【算法刷题日记之本手篇】星际密码与数根

热门文章

  1. java写弹力球游戏,用Qt5做的弹力球小游戏
  2. ganymed ssh-2 for java_如何利用Ganymed SSH-2模拟SSH操作
  3. Sonar指定Java项目分析文件
  4. 我给航母做3D还原:这三处细节,太震撼了…
  5. 图像标记img的title属性
  6. 一个叫“老骆驼”的信息安全专家手机被偷,顺藤摸瓜揭开了移动支付的漏洞!
  7. “俄罗斯讨论自研游戏引擎”解读
  8. Spring-Cloud-Config快速开始
  9. 突破百度硬盘限制速度的傻瓜教程(非迅雷),20210630亲测可用
  10. 关于使用iMAG.js出现的问题及解决方法