标签:memset 条件 记录 出现 case continue while class namespace
题目大意:
有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】(经典)
标签:memset 条件 记录 出现 case continue while class namespace
原文地址:https://www.cnblogs.com/-Ackerman/p/11296918.html