话说最近几天我为什么就跟
S
P
F
A
SPFA
SPFA淦上了…
不多说了直接入题
luoguP3385【模板】负环
这道题只求一个图中是否有原点能到达的负环 显然用
b
f
s
bfs
bfs版的
S
P
F
A
SPFA
SPFA判负环就可过
具体说一下就是 每个点最多只能与
n
−
1
n-1
n−1个点相连 如果进队次数超过
n
n
n说明算法已经走进了一个负环
上代码
#include<bits/stdc++.h>
using namespace std;
#define reg register
#define N 2002
#define M 10010
inline void read(int &x){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
queue<int> q;
int T,n,m,x,y,z,tot,head[N],cnt[N],dis[N];
bool vis[N];
struct node
{
int to,nxt,val;
}edge[M];
inline void addedge(int u, int v, int w){
edge[++tot].to=v;
edge[tot].val=w;
edge[tot].nxt=head[u];
head[u]=tot;
}
inline void superadd(int u, int v, int w){
addedge(u,v,w);addedge(v,u,w);
}
bool spfa(int s){
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(reg int i=head[u];i;i=edge[i].nxt){
int vv=edge[i].to;
if(dis[vv]>dis[u]+edge[i].val){
dis[vv]=dis[u]+edge[i].val;
if(!vis[vv])
{
vis[vv]=true;
cnt[vv]++;
if(cnt[vv]>n)return false;
q.push(vv);
}
}
}
}
return true;
}
int main()
{
read(T);
while(T--)
{
memset(head,0,sizeof(head));
memset(cnt,0,sizeof(cnt));
memset(vis,0,sizeof(vis));
memset(dis,0x7f,sizeof(dis));
memset(edge,0,sizeof(edge));
dis[1]=tot=0;
read(n),read(m);
for(reg int i=1;i<=m;i++){
read(x),read(y),read(z);
if(z<0)addedge(x,y,z);
else superadd(x,y,z);
}
if(!spfa(1))puts("YE5");
else puts("N0");
}
}
luoguP3199 [HNOI2009]最小圈
本题求一个图中平均权值最小的那个环
显然需要二分 每取到一个
m
i
d
mid
mid,
c
h
e
c
k
check
check一下所有边权减去
m
i
d
mid
mid图有没有负环。 如果有
r
=
m
i
d
r=mid
r=mid,否则
l
=
m
i
d
l=mid
l=mid
题解里的
01
01
01分数规划是什么奇怪怪的东西咱也不懂 咱也不敢问 二分就完了
由于需要多次求负环所以显然
d
f
s
dfs
dfs版的
S
P
F
A
SPFA
SPFA判负环更优
b
f
s
bfs
bfs会导致
T
L
E
TLE
TLE
P
S
:
PS:
PS:大哥:我最短路用
d
i
j
k
s
t
r
a
dijkstra
dijkstra负环用
d
f
s
dfs
dfs什么
S
P
F
A
SPFA
SPFA 啥的 他已经死了
上代码
#include<bits/stdc++.h>
using namespace std;
#define reg register
#define N 3003
#define M 10010
int n,m,x,y,tot,head[N];
double dis[N],z,l=-1e9,r=1e9,mid,eps=1e-8;
bool vis[N];
struct node
{
int to,nxt;
double val;
}edge[M<<1];
inline void addedge(int u, int v, double w){
edge[++tot].to=v;
edge[tot].val=w;
edge[tot].nxt=head[u];
head[u]=tot;
}
inline void superadd(int u, int v, double w){
addedge(u,v,w);addedge(v,u,w);
}
inline bool spfa(int s){
vis[s]=true;
for(reg int i=head[s];i;i=edge[i].nxt){
int vv=edge[i].to;
if(dis[vv]>dis[s]+edge[i].val-mid){
dis[vv]=dis[s]+edge[i].val-mid;
if(vis[vv]){vis[vv]=false;return true;}
if(spfa(vv)){vis[vv]=false;return true;}
}
}
return vis[s]=false;
}
inline bool check(){
memset(dis,0,sizeof(dis));
for(reg int i=1;i<=n;i++)if(spfa(i))return true;
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(reg int i=1;i<=m;i++){
scanf("%d%d%lf",&x,&y,&z);
addedge(x,y,z);
}
while(r-l>=eps){
mid=(l+r)/2.0;
if(check())r=mid;
else l=mid;
}
printf("%.8lf\n",r);
}
就写这么多吧 由于我对新算法的渴望 (其实是懒 所以不详细解释了
有问题可以写到下面的评论区 或者加
Q
Q
407694747
QQ407694747
QQ407694747 我们一起讨论
请各路神犇诸位大佬请多多指教!