spfa判负环,当访问次数大于n时,说明当前点在负环中,利用dfs把与他相连的点标记。
我遇到到的问题是我用矩阵存图,不通的路标记INF,如果没有负权值是可以直接不用管是否通,直接更新就行。有负权值时,须判断是否通路,因为对于dist[i]>dist[u]+dap[u][i],当dap[u][i]=inf时,不能到达i,但如果dist[u]<0,就会更新i。用vector存图就不用了。
#include <iostream>
#include<string.h>
#include<stdio.h>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
int ss[205],dap[205][205],dist[205];
int cur[205];
int n,m,s,e;
void dfs(int x)
{
cur[x]=1;
for(int i=1; i<=n; i++)
{
if(dap[x][i]!=inf&&cur[i]==0)/
dfs(i);
}
}
void dijst()
{
int vis[205];
int cut[205];
memset(cut,0,sizeof(cut));
memset(vis,0,sizeof(vis));
queue<int>p;
p.push(1);
dist[1]=0;
vis[1]=1;
cut[1]++;
while(!p.empty())
{
int u=p.front();
p.pop();
vis[u]=0;
for(int i=1; i<=n; i++)
{
if(dap[u][i]==inf||cur[i]==1)
continue;
if(dist[i]>dist[u]+dap[u][i])
{
dist[i]=dist[u]+dap[u][i];
if(vis[i]==0)
{
cut[i]++;
vis[i]=1;
p.push(i);
if(cut[i]>n)
dfs(i);
}
}
}
}
}
int main()
{
int t,top=0,q;
scanf("%d",&t);
while(t--)
{
memset(cur,0,sizeof(cur));
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&ss[i]);
memset(dist,inf,sizeof(dist));
memset(dap,inf,sizeof(dap));
scanf("%d",&m);
for(int i=0; i<m; i++)
{
scanf("%d%d",&s,&e);
dap[s][e]=(ss[e]-ss[s])*(ss[e]-ss[s])*(ss[e]-ss[s]);
}
scanf("%d",&q);
printf("Case %d:\n",++top);
dijst();
for(int i=0; i<q; i++)
{
scanf("%d",&s);
if(cur[s]||dist[s]<3||dist[s]==inf)
printf("?\n");
else
printf("%d\n",dist[s]);
}
}
return 0;
}