1. 程式人生 > >LightOJ 1074 - Extended Traffic 【SPFA】

LightOJ 1074 - Extended Traffic 【SPFA】

set dijk 否則 出現 ont empty tps ffi 題目

<題目鏈接>

題目大意:
有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:\n",++ncase); scanf("%d",&m); while(m--){ int u;scanf("%d",&u); if(cir[u] || dist[u]<3 || dist[u] == INF) //如果詢問的點能由負環達到、或者到起點的最小受益小於3、或者詢問的點不可達 printf("?\n"); else printf("%d\n",dist[u]); } } return 0; }

2018-08-31

LightOJ 1074 - Extended Traffic 【SPFA】