这一片文章把整个图论的知识都用上了,基础芝士如下
Peter算法小课堂—Dijkstra最短路算法-CSDN博客
二话不说,题呢?
罗密欧与朱丽叶
你是罗密欧,要去找朱丽叶。共有n个城市,编号1到n,你在1号城市,朱丽叶在n号。城市间共有m条双向道路,路程长度都已知。求你去找朱丽叶的路径中最长一段道路最短是多少?若无法到达输出-1。
看到题目大家可能并不能一下子写出代码,给大家讲讲遇到图论,怎么办?①背最短路问题模板②背最小生成树模板③背强连通分量④背欧拉回路
于是,脑子里浮现出许多算法:二分、Dijkstra、最小生成树
二分枚举
大家学过二分,来先写一下代码
bool OK(){
fill(vst,vst+n+1,0);
dfs(1);
return vst[n];
}
ll l=0,r=1000,ans=-1;
while(l<=r){
mid=l+(r-l)/2;
if(OK()) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;
void dfs(int x){
vst[x]=1;
if(vst[n]) return;
for(int i=n;i>=2;i--){
if(!vst[i]&&A[x][i]<=mid)
dfs(i);
}
}
最小生成树
二分完了之后搞一个MST
ll kruskal(){
sort(e,e+m,cmp);
for(ll i=1;i<=n;i++) id[i]=i;
ll ans=0;
for(ll k=0;k<m;k++){
ll fa=find(e[k].a),fb=find(e[k].b);
if(fa=fa) continue;
id[fa]=fb;
if(find(1)==find(n)) return e[k].w;
}
return -1;
}
最短路
void dijkstra(){
fill(d,d+n+9,INF);
fill(ok,ok+n+9,0);
d[1]=0;
for(ll k=1;k<=n;k++){
ll u=n+1;
for(ll v=1;v<=n;v++)
if(!ok[v]&&d[v]<d[u]) u=v;
ok[u]=1;
if(u==n||u==n+1) break;
for(ll i=0;i<to[u].size();i++)
d[to[u][i]]=min(d[to[u][i]],max(d[u],w[u][i]));
}
}
结束了?