LightOJ 1074 - Extended Traffic SPFA(经典)
Posted -ackerman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOJ 1074 - Extended Traffic SPFA(经典)相关的知识,希望对你有一定的参考价值。
题目大意:
有n个城市,每一个城市有一个拥挤度Ai,从一个城市I到另一个城市J的时间为:(A(v)-A(u))^3。问从第一个城市到达第k个城市所花的时间,如果不能到达,或者时间小于3输出?否则输出所花的时间。
解题分析:
很明显,此题路段的权值可能为负,所以我们就不能用Dijkstra算法求最短路了。需要注意的是,当点存在负环的时候,就要将负环所能够到达的所有点全部标记,从起点到这些点的最短路是不存在的(因为假设如果存在最短路,那么只要途中在负环上多走几遍,那么重新算得的时间一定会变少,所以不存在最短路)。所以,总的来说,对于本题,对那些负环能够到达的点,和从起点无法到达的点,和时间小于3的点,全部输出“?”,其他满足条件的直接输出最短时间就行。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 8 9 const int MAXN=220; 10 const int INF =0x3f3f3f3f; 11 12 struct Edge 13 int to; 14 int next; 15 int val; 16 edge[MAXN*MAXN]; 17 18 int res,n; 19 int head[MAXN]; 20 bool vis[MAXN]; //记录该点是否在队列内 21 bool cir[MAXN]; //记录该点是否为负环上的点 22 int a[MAXN],dist[MAXN],cnt[MAXN]; //cnt[]数组记录该数在队列中出现的次数 23 24 void dfs(int u) //将该负环所能够达到的所有点全部标记 25 cir[u]=true; 26 for(int i=head[u];i!=-1;i=edge[i].next) 27 int v=edge[i].to; 28 if(!cir[v])dfs(v); 29 30 31 32 void init() 33 memset(head,-1,sizeof(head)); 34 res=0; 35 36 37 void add(int u,int v,int w) 38 edge[res].to=v,edge[res].val=w; 39 edge[res].next=head[u]; 40 head[u]=res++; 41 42 43 void SPFA(int st) 44 memset(vis,false,sizeof(vis)); 45 memset(cir,false,sizeof(cir)); 46 memset(cnt,0,sizeof(cnt)); 47 for(int i=1;i<=n;i++) 48 dist[i]=INF; 49 dist[st]=0; 50 queue<int>q; 51 q.push(st); 52 cnt[st]=1; 53 vis[st]=true; 54 while(!q.empty()) 55 int u=q.front(); 56 q.pop(); 57 vis[u]=false; //当该点从队列中pop掉之后,就要清除vis标记 58 for(int i=head[u];i!=-1;i=edge[i].next) 59 int v=edge[i].to; 60 if(cir[v])continue; //如果是负环上的点 61 if(dist[v]>dist[u]+edge[i].val) 62 dist[v]=dist[u]+edge[i].val; 63 if(!vis[v]) //如果该点不在队列中 64 vis[v]=true; 65 q.push(v); 66 cnt[v]++; 67 if(cnt[v]>n) //若存在负环,就用dfs将该负环能够达到的所有点标记 68 dfs(v); 69 70 71 72 73 74 75 76 int main() 77 int t;scanf("%d",&t); 78 int ncase=0; 79 while(t--) 80 init(); 81 scanf("%d",&n); 82 for(int i=1;i<=n;i++) 83 scanf("%d",&a[i]); 84 int m; 85 scanf("%d",&m); 86 while(m--) 87 int u,v; 88 scanf("%d %d",&u,&v); 89 add(u,v,(a[v]-a[u])*(a[v]-a[u])*(a[v]-a[u])); 90 91 92 SPFA(1); 93 printf("Case %d:\n",++ncase); 94 scanf("%d",&m); 95 while(m--) 96 int u;scanf("%d",&u); 97 if(cir[u] || dist[u]<3 || dist[u] == INF) //如果询问的点能由负环达到、或者到起点的最小受益小于3、或者询问的点不可达 98 printf("?\n"); 99 else printf("%d\n",dist[u]); 100 101 102 return 0; 103
以上是关于LightOJ 1074 - Extended Traffic SPFA(经典)的主要内容,如果未能解决你的问题,请参考以下文章
LightOj1074 - Extended Traffic(SPFA最短路)
Extended Traffic LightOJ - 1074 spfa判断负环
LightOJ 1074 - Extended Traffic SPFA
LightOJ - 1074 Extended Traffic(标记负环)