AcWing 904. 虫洞(SPFA or Djakarta or bellman判负环)
Posted MangataTS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 904. 虫洞(SPFA or Djakarta or bellman判负环)相关的知识,希望对你有一定的参考价值。
题目连接
http://poj.org/problem?id=3259
思路
大概是想问我们能不能找到一个负环,那么再看一眼数据范围,500,感觉乱搞都能过,但是出题人很恶心啊,n的范围并不是500,卡了巨久,但是用Floyd
也是能过的,只不过写的时候要注意自己的常数,常数打了就过不了了,但是想到判负环我们应该联想到spfa
和bellman
算法,详情请看:spfa和bellman判负环,由于spfa
算法是优化后的bellman所以我这里就不放bellman的代码了
代码
Floyd算法
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e3+10;
int n,m,w;
int f[N][N];
bool floyd()
for(int k = 1;k <= n; ++k)
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= n; ++j)
if(f[i][j] > f[i][k] + f[k][j])
f[i][j] = f[i][k] + f[k][j];
if(f[i][i] < 0) return true;
return false;
void slove()
scanf("%d%d%d",&n,&m,&w);
int u,v,k;
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= n; ++j)
f[i][j] = (i == j?0:INF);
for(int i = 1;i <= m; ++i)
scanf("%d%d%d",&u,&v,&k);
if(f[u][v] > k)
f[u][v] = f[v][u] = k;
for(int i = 1;i <= w; ++i)
scanf("%d%d%d",&u,&v,&k);
f[u][v] = -k;
if(floyd()) puts("YES");
else puts("NO");
int main()
int t;
scanf("%d",&t);
while(t--)
slove();
return 0;
spfa算法
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
//----------------自定义部分----------------
#define ll long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f
int dx[4]=0,-1,0,1,dy[4]=-1,0,1,0;
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=1LL)
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
return ans;
ll lowbit(ll x)return -x & x;
const int N = 2e6+10;
//----------------自定义部分----------------
int n,m,q,w;
vector<PII> E[N];
int dis[N],cnt[N];
bool vis[N];
void spfa()
queue<int> que;
for(int i = 1;i <= n; ++i) que.push(i);
while(!que.empty())
int t = que.front();
que.pop();
vis[t] = false;//表明t这个点已经离开这个队列了
for(int i = 0,l = E[t].size();i < l; ++i)
int j = E[t][i].first,k = E[t][i].second;
if(dis[j] > dis[t] + k)
dis[j] = dis[t] + k;
cnt[j] = cnt[t] + 1;
if(cnt[j] >= n) //找到负环
puts("YES");
return;
if(!vis[j])//将j这个点重新加入队列
que.push(j),vis[j] = true;
puts("NO");
void init()
for(int i = 1;i <= n; ++i) E[i].clear(),vis[i] = true,cnt[i] = 0;
void slove()
scanf("%d%d%d",&n,&m,&w);
init();
int u,v,k;
for(int i = 1;i <= m; ++i)
scanf("%d%d%d",&u,&v,&k);
E[u].push_back(v,k);
E[v].push_back(u,k);
for(int i = 1;i <= w; ++i)
scanf("%d%d%d",&u,&v,&k);
E[u].push_back(v,-k);
spfa();
int main()
int t;
scanf("%d",&t);
while(t--)
slove();
return 0;
以上是关于AcWing 904. 虫洞(SPFA or Djakarta or bellman判负环)的主要内容,如果未能解决你的问题,请参考以下文章
AcWing 852. spfa判断负环(spfa or bellman)
bzoj 1715: [Usaco2006 Dec]Wormholes 虫洞spfa判负环
POJ 3259 Wormholes最短路/SPFA判断负环模板
POJ-3259 Wormholes---SPFA判断有无负环