边上带有负值的单源最短路径。
Bellman-Ford算法:
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 2000+5
#define INF 1000000
using namespace std;
int u[MAXN],v[MAXN],w[MAXN],n,m,d[1005];
int main()
{
// freopen("in.txt","r",stdin);
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
scanf("%d%d%d",&u[i],&v[i],&w[i]);
for(int i=0;i<n;i++)
d[i]=INF;
d[0]=0;
for(int k=0;k<n-1;k++)
{
for(int i=0;i<m;i++)
{
int x=u[i],y=v[i];
if(d[x]<INF) d[y]=min(d[y],d[x]+w[i]);
}
}
bool ok=false;
for(int i=0;i<m;i++)
{
int x=u[i],y=v[i];
if(d[x]<INF&&d[y]>d[x]+w[i])
{
ok=true;
puts("possible");
break;
}
}
if(!ok)
puts("not possible");
}
return 0;
}
SPFA算法(邻接表):
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#define MAXN 2000+5
#define INF 1000000
using namespace std;
int u[MAXN],v[MAXN],w[MAXN],n,m,d[1005],first[1005],next[MAXN];
void read_graph()
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
first[i]=-1;
for(int e=0; e<m; e++)
{
scanf("%d%d%d",&u[e],&v[e],&w[e]);
next[e]=first[u[e]];
first[u[e]]=e;
}
}
bool ok;
void spfa()
{
queue<int>q;
ok=false;
int vis[1005];
memset(vis,0,sizeof(vis));
bool inq[1005];
d[0]=0;
for(int i=1;i<n;i++)
d[i]=INF;
memset(inq,0,sizeof(inq));
q.push(0);
while(!q.empty())
{
int x=q.front();q.pop();
inq[x]=false;
for(int e=first[x];e!=-1;e=next[e])
{
if(d[v[e]]>d[x]+w[e])
{
d[v[e]]=d[x]+w[e];
if(!inq[v[e]])
{
inq[v[e]]=true;
vis[v[e]]++;
if(vis[v[e]]>n)
{
ok=true;
return ;
}
q.push(v[e]);
}
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int cas;
scanf("%d",&cas);
while(cas--)
{
read_graph();
spfa();
if(ok)
puts("possible");
else puts("not possible");
}
return 0;
}