LightOJ 1074 - Extended Traffic SPFA
Posted 00isok
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOJ 1074 - Extended Traffic SPFA相关的知识,希望对你有一定的参考价值。
<题目链接>
题目大意:
有n个城市,每一个城市有一个拥挤度Ai,从一个城市I到另一个城市J的时间为:(A(v)-A(u))^3。问从第一个城市到达第k个城市所花的时间,如果不能到达,或者时间小于3输出?否则输出所花的时间。
解题分析:
很明显,此题路段的权值可能为负,所以我们就不能用Dijkstra算法求最短路了。需要注意的是,当点存在负环的时候,就要将负环所能够到达的所有点全部标记,从起点到这些点的最短路是不存在的(因为假设如果存在最短路,那么只要途中在负环上多走几遍,那么重新算得的时间一定会变少,所以不存在最短路)。所以,总的来说,对于本题,对那些负环能够到达的点,和从起点无法到达的点,和时间小于3的点,全部输出“?”,其他满足条件的直接输出最短时间就行。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; const int MAXN=220; const int INF =0x3f3f3f3f; struct Edge{ int to; int next; int val; }edge[MAXN*MAXN]; int res,n; int head[MAXN]; bool vis[MAXN]; //记录该点是否在队列内 bool cir[MAXN]; //记录该点是否为负环上的点 int a[MAXN],dist[MAXN],cnt[MAXN]; //cnt[]数组记录该数在队列中出现的次数 void dfs(int u){ //将该负环所能够达到的所有点全部标记 cir[u]=true; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(!cir[v])dfs(v); } } void init(){ memset(head,-1,sizeof(head)); res=0; } void add(int u,int v,int w){ edge[res].to=v,edge[res].val=w; edge[res].next=head[u]; head[u]=res++; } void SPFA(int st){ memset(vis,false,sizeof(vis)); memset(cir,false,sizeof(cir)); for(int i=1;i<=n;i++) dist[i]=INF; vis[st]=true; dist[st]=0; queue<int>q; q.push(st); memset(cnt,0,sizeof(cnt)); cnt[st]=1; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=false; //当该点从队列中pop掉之后,就要清除vis标记 for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(cir[v])continue; //如果是负环上的点 if(dist[v]>dist[u]+edge[i].val){ dist[v]=dist[u]+edge[i].val; if(!vis[v]){ //如果该点不在队列中 vis[v]=true; q.push(v); cnt[v]++; if(cnt[v]>n){ //若存在负环,就用dfs将该负环能够达到的所有点标记 dfs(v); } } } } } } int main(){ int t;scanf("%d",&t); int ncase=0; while(t--){ init(); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int m; scanf("%d",&m); while(m--){ int u,v; scanf("%d %d",&u,&v); add(u,v,(a[v]-a[u])*(a[v]-a[u])*(a[v]-a[u])); } SPFA(1); printf("Case %d: ",++ncase); scanf("%d",&m); while(m--){ int u;scanf("%d",&u); if(cir[u] || dist[u]<3 || dist[u] == INF) //如果询问的点能由负环达到、或者到起点的最小受益小于3、或者询问的点不可达 printf("? "); else printf("%d ",dist[u]); } } return 0; }
2018-08-31
以上是关于LightOJ 1074 - Extended Traffic SPFA的主要内容,如果未能解决你的问题,请参考以下文章
LightOj1074 - Extended Traffic(SPFA最短路)
Extended Traffic LightOJ - 1074 spfa判断负环
LightOJ 1074 - Extended Traffic SPFA
LightOJ - 1074 Extended Traffic(标记负环)