• LightOJ 1074


    题目大意:
    有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:
    ",++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("?
    ");
     99             else printf("%d
    ",dist[u]);
    100         }
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    iOS----------WKWebView修改userAgent
    Vmware路由配置
    【手机APP开发】指南
    【Git】git 指南
    【微信小程序开发】阮一峰老师的微信小程序开发入门教程——学起来~
    【vue】2-Keycode对照表
    【vue】1-vue简介与基础
    Meaning
    数据增强
    Dropout
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11296918.html
Copyright © 2020-2023  润新知