并不对劲的图论专题(三):SPFA算法的优化
1.bzoj1489->
这是个新套路。
我们希望找到最小的x,那么可以二分x,然后判断是否存在圈的边权的平均值小于等于x。
设圈的边权依次为w1,w2,w3,…,wk,平均值为p,
则有p= (w1+w2+w3+…+wk)/k ,
可以推出p*k=w1+w2+w3+…+wk,
这样就会有(w1-p)+(w2-p)+…+(wk-p)=0,
当p≤x时,就会有(w1-x)+(w2-x)+…+(wk-x)≤0。
这样,可以通过把所有边的边权都改为w-x,然后通过判断负环得出存在圈的边权的平均值小于等于x。
代码,不知为何常数极大:
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define maxn 3010
#define maxm 10010
#define eps 1e-10
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(isdigit(ch)==0 && ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(int x)
{
int f=0;char ch[20];
if(!x){puts("0");return;}
if(x<0){putchar('-');x=-x;}
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
}
int fir[maxn],nxt[maxm],v[maxm],cnt,n,m,inf[5],vis[maxn],yes;
double mid,ans,L,R,dis[maxn],w[maxm];
void ade(int u1,int v1,double w1){v[cnt]=v1,w[cnt]=w1,nxt[cnt]=fir[u1],fir[u1]=cnt++;}
void dfs(int u)
{
if(yes)return;
for(int k=fir[u];k!=-1;k=nxt[k])
{
if(dis[v[k]]>dis[u]+(w[k]-mid))
{
dis[v[k]]=dis[u]+(w[k]-mid);
if(vis[v[k]]){yes=1;return;}
vis[v[k]]=1,dfs(v[k]),vis[v[k]]=0;
}
else if(dis[v[k]]==dis[u]+(w[k]-mid)){if(vis[v[k]]){yes=1;return;}vis[v[k]]=1,dfs(v[k]),vis[v[k]]=0;}
}
}
int check()
{
yes=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)dis[j]=0.0,vis[j]=0;
dfs(i);
if(yes)break;
}
return yes;
}
int main()
{
memset(inf,31,sizeof(inf));
memset(fir,-1,sizeof(fir));
n=read(),m=read();L=10000000.0,R=-10000000.0;
for(int i=1;i<=m;i++){int x=read(),y=read();double z;scanf("%lf",&z);R=max(z,R),L=min(z,L);ade(x,y,z);}ans=R;
while(fabs(R-L)>eps)
{
mid=(L+R)/2.0;int f=check();
//cout<<L<<" "<<mid<<" "<<R<<endl;
if(f)ans=ans<mid?ans:mid,R=mid-eps;
else L=mid+eps;
}
printf("%.8lf",ans);
return 0;
}
2.bzoj1715->
判负环就ok。
说个小技巧:一开始将所有点的距离设为0,而不是正无穷,这样遇到负数才会更新。
说另一个小技巧:将bfs改成dfs,在判负环时可能会更优秀,但是有可能被卡,比如上一题。
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define maxn 505
#define maxm 6010
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(isdigit(ch)==0 && ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(int x)
{
int f=0;char ch[20];
if(!x){puts("0");return;}
if(x<0){putchar('-');x=-x;}
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
}
int T,n,m,ww,fir[maxn],dis[maxn],nxt[maxm],v[maxm],w[maxm],vis[maxn],cnt,yes;
void ade(int u1,int v1,int w1){v[cnt]=v1,w[cnt]=w1,nxt[cnt]=fir[u1],fir[u1]=cnt++;}
void reset(){memset(fir,-1,sizeof(fir)),memset(vis,0,sizeof(vis));cnt=yes=0;}
void dfs(int u)
{
if(yes)return;
for(int k=fir[u];k!=-1;k=nxt[k])
{
if(dis[v[k]]>dis[u]+w[k])
{
// cout<<dis[v[k]]<<" "<<dis[u]<<" "<<u<<" "<<v[k]<<endl;
dis[v[k]]=dis[u]+w[k];
if(vis[v[k]]){yes=1;/*cout<<v[k]<<endl;*/break;}
vis[v[k]]=1;
dfs(v[k]);
vis[v[k]]=0;
}
}
}
int main()
{
T=read();
while(T--)
{
reset();
n=read(),m=read(),ww=read();
for(int i=1;i<=m;i++){int x=read(),y=read(),z=read();ade(x,y,z),ade(y,x,z);}
for(int i=1;i<=ww;i++){int x=read(),y=read(),z=read();ade(x,y,-z);}
for(int i=1;i<=n&&!yes;i++){memset(dis,0,sizeof(dis));vis[i]=1;dfs(i);vis[i]=0;}
puts(yes?"YES":"NO");
}
return 0;
}
3.vijos1053->
板子题,代码就不贴了。
说下SLF优化:如果有一个点的距离被更新时,小于队列当前队首的距离,那么就把它放到队首。
它的依据在于,不存在负权边的情况下,队首的元素比它大,更新的点不会比它更优,也就是类似dijkstra的贪心。
但是,存在负权边时,这个优化就变得玄学了。比如点x入队时,队首y的距离大于x的,将x放在队首。但是存在一条y->x的负权边,在算y时又更新了x的距离,就让x额外入队了一次。
今天的超链接图是银火龙呢。
并不对劲的图论专题(三):SPFA算法的优化的更多相关文章
- 关于SPFA算法的优化方式
关于SPFA算法的优化方式 这篇随笔讲解信息学奥林匹克竞赛中图论部分的求最短路算法SPFA的两种优化方式.学习这两种优化算法需要有SPFA朴素算法的学习经验.在本随笔中SPFA朴素算法的相关知识将不予 ...
- 【uva 658】It's not a Bug, it's a Feature!(图论--Dijkstra或spfa算法+二进制表示+类“隐式图搜索”)
题意:有N个潜在的bug和m个补丁,每个补丁用长为N的字符串表示.首先输入bug数目以及补丁数目.然后就是对M个补丁的描述,共有M行.每行首先是一个整数,表明打该补丁所需要的时间.然后是两个字符串,第 ...
- 《SPFA算法的优化及应用》——姜碧野(学习笔记)
一.核心性质:三角不等式.最短路满足d[v]<=d[u]+w(u,v) 二.SPFA两种实现: 常见的是基于bfs的,这是直接对bellman-ford用队列维护.根据最短路的长度最长为(n-1 ...
- 图论——最小生成树:Prim算法及优化、Kruskal算法,及时间复杂度比较
最小生成树: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.简单来说就是有且仅有n个点n-1条边的连通图. 而最小生成树就是最小权 ...
- 蓝书3.3 SPFA算法的优化
T1 最小圈 bzoj 1486 题目大意: 一个环的权值平均值为定义为一个这个环上所有边的权值和除以边数 求最小的环的权值平均值 思路: 二分一个值 把所有边减去这个值 判断是否有负环 #inclu ...
- 最短路问题的三种算法&模板
最短路算法&模板 最短路问题是图论的基础问题.本篇随笔就图论中最短路问题进行剖析,讲解常用的三种最短路算法:Floyd算法.Dijkstra算法及SPFA算法,并给出三种算法的模板.流畅阅读本 ...
- 队列优化dijsktra(SPFA)的玄学优化
转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2 优化 对一些数 ...
- 图论算法(三) 最短路SPFA算法
我可能要退役了…… 退役之前,写一篇和我一样悲惨的算法:SPFA 最短路算法(二)SPFA算法 Part 1:SPFA算法是什么 其实呢,SPFA算法只是在天朝大陆OIers的称呼,它的正统名字叫做: ...
- [hihoCoder] #1093 : 最短路径·三:SPFA算法
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的晚上,小Hi和小Ho在吃过晚饭之后,来到了一个巨大的鬼屋! 鬼屋中一共有N个地点,分别编号为1..N,这N个地点之 ...
随机推荐
- (4)主成分分析Principal Component Analysis——PCA
主成分分析Principal Component Analysis 降维除了便于计算,另一个作用就是便于可视化. 主成分分析-->降维--> 方差:描述样本整体分布的疏密,方差越大-> ...
- 线性回归Linear regression
线性回归算法 解决回归问题 思想简单,容易实现 是许多强大的非线性模型的基础 结果具有很好的可解释性 蕴含机器学习中的很多重要思想 基本思想:寻找一条直线,最大程度的“拟合”样本特征和样本输出标记之间 ...
- 准确率(Precision),召回率(Recall)以及综合评价指标(F1-Measure)
准确率和召回率是数据挖掘中预测,互联网中得搜索引擎等经常涉及的两个概念和指标. 准确率:又称“精度”,“正确率” 召回率:又称“查全率” 以检索为例,可以把搜索情况用下图表示: 相关 不相关 检索 ...
- CSU 1307 最短路+二分
题目大意: 帮忙找到一条a到b的最短路,前提是要保证路上经过的站点的最大距离尽可能短 这道题居然要用到二分...完全没去想过,现在想想求最大距离的最小值确实是... 这里不断二分出值代入spfa()或 ...
- 【组合 数学】codeforces C. Do you want a date?
codeforces.com/contest/810/problem/C [题意] 给定一个集合A,求 , 输入: [思路] 基数为n的集合有2^n-1个非空子集. 首先n个数要从小到大排序,枚举最后 ...
- CCF 201712-4 90分
90分,不知道错在哪里了,dijkstra算法,用一个数组的d[i]表示以i点结尾的小路的长度,以i点为中心扩展时,若下一点为k,如果i->k是小路,则 d[j] = d[k]+M[k][j]; ...
- 使用Windows系统远程连接Windows server服务器
点击开始菜单->运行 (或者 windows+R) ,输入"mstsc"命令, 打开远程桌面连接对话框,输入你要连接的Windows server服务器的公网IP. 点击 ...
- Python基础教程笔记——第6章:抽象(函数)
(1)计算裴波那契数列: fbis=[0,1] num=int(input("please input the number")) for i in range(num-2): f ...
- poj2723 2sat判断解+二分
典型的2-sat问题,题意:有m个门,每个门上俩把锁,开启其中一把即可,现在给n对钥匙(所有 钥匙编号0123456...2n-1),每对钥匙只能用一把,要求尽可能开门多(按顺序,前max个). 关键 ...
- 洛谷——P2865 [USACO06NOV]路障Roadblocks
P2865 [USACO06NOV]路障Roadblocks 题目描述 Bessie has moved to a small farm and sometimes enjoys returning ...