题意:有n个点,m条有向边,每条边的权值等于(弧头的权值-弧尾的权值)的三次方,求第一个点到给定点的最短路径;
用dijkstra做了一遍,WA,再读一遍题发现边的权值可以为负,可能会产生负环,把负环上的所有点还有路径经过负环的点都标记,此处用一个dfs;
用spfa+邻接表做了一遍,期间犯了很多小错误,改了很久,RE了很多次终于过了,还是太不仔细了;
#include <iostream> #include<cmath> #include<cstdio> #include<cstring> #define N 220 #define M 44000 #define INF 0x3f3f3f3f using namespace std; struct node { int next,val,to; }e[M]; int head[N],d[N],mark[N],v[N],num[N],n,m,point[N],q[N]; int busyness(int a,int b) { int t=point[b]-point[a]; return t*t*t; } void dfs(int t) { mark[t]=1; for(int i=head[t];i!=-1;i=e[i].next) if(!mark[e[i].to]) dfs(e[i].to); } void spfa() { memset(num,0,sizeof(num)); memset(mark,0,sizeof(mark)); for(int i=1;i<=n;i++) v[i]=0,d[i]=INF; d[1]=0; v[1]=1; int cnt=0; q[0]=1; num[1]=1; while(cnt>=0) { int t=q[cnt--]; v[t]=0; if(mark[t]) continue; for(int i=head[t];i!=-1;i=e[i].next) { int b=e[i].to; if(mark[b]) continue; if(d[b]>d[t]+e[i].val) { d[b]=d[t]+e[i].val; if(!v[b]) { q[++cnt]=b; v[b]=1; if(++num[b]>n) dfs(b); } } } } } int main() { int T; cin>>T; for(int kase=1;kase<=T;kase++) { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&point[i]),head[i]=-1; cin>>m; for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); e[i].to=b; e[i].next=head[a]; e[i].val=busyness(a,b); head[a]=i; } spfa(); int q; cin>>q; printf("Case %d:\n",kase); for(int i=0;i<q;i++) { int x; scanf("%d",&x); if(d[x]==INF||d[x]<3||mark[x]) cout<<'?'<<endl; else cout<<d[x]<<endl; } } }