题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4812
思路:若存在负环且0点在负环中,则有解。则用SPFA判断是否存在负环,若点i在负环中,则该点的dist置为-INF(下次不再访问),若某点已在负环中,则更新时该点无需进入队列。所以若0点在某个负环中,则dist[0]<0,判断一下即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+50;
const int INF=0x3f3f3f3f;
struct Node
{
int v,w;
Node(int v=0,int w=0):v(v),w(w) {}
};
int n,m;
int inq[maxn];
queue<int> q;
int dist[maxn],v[maxn];
vector<Node> g[maxn];
int solve(int x)
{
memset(v,0,sizeof(v));
memset(inq,0,sizeof(inq));
while(!q.empty()) q.pop();
for(int i=0; i<=n; i++) dist[i]=INF;
dist[x]=0,q.push(x),v[x]=1,inq[x]++;
while(!q.empty())
{
int now=q.front();
q.pop(),v[now]=0;
for(int i=0; i<g[now].size(); i++)
{
int nt=g[now][i].v;
if(dist[nt]>dist[now]+g[now][i].w)
{
int flag=0;
dist[nt]=dist[now]+g[now][i].w;
if(!v[nt]&&inq[nt]<=(int)sqrt(n))
{
flag=1;
v[nt]=1;
q.push(nt);
inq[nt]++;
}
if(inq[nt]>(int)sqrt(n)&&flag) dist[nt]=-INF;
}
}
}
return dist[0]<0;
}
int main()
{
int t,cas=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++) g[i].clear();
for(int i=0; i<m; i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
g[x].push_back(Node(y,w));
}
if(solve(0)) printf("Case #%d: possible\n",++cas);
else printf("Case #%d: not possible\n",++cas);
}
return 0;
}