• Luogu P1119 灾后重建 【floyd】By cellur925


    题目传送门

    这道题我们很容易想到对于每次询问,都跑一遍最短路(spfa,虽然他已经死了)。只需在松弛的时候加入当前相关的点是否已经修好的判断,果不其然的TLE了4个点。

    (然鹅我第一次用spfa跑的时候竟然全WA了,震惊!由于节点从0开始标号,所以head数组要预处理为-1,遍历的时候for(int i=head[x];i!=-1;i=edge[i].next啊啊啊啊啊

    Code_TLE

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<queue>
     5 
     6 using namespace std;
     7 const int inf=2147483647;
     8 
     9 int n,m,Q,tot;
    10 int ddl[250],dis[250],head[250];
    11 bool vis[250];
    12 struct node{
    13     int next,to,val;
    14 }edge[32000];
    15 
    16 void add(int x,int y,int z)
    17 {
    18     edge[++tot].to=y;
    19     edge[tot].val=z;
    20     edge[tot].next=head[x];
    21     head[x]=tot;
    22 }
    23 
    24 int spfa_ask(int s,int t,int T)
    25 {
    26     memset(vis,0,sizeof(vis));
    27     for(int i=0;i<n;i++) dis[i]=inf;
    28     queue<int>q;
    29     q.push(s);dis[s]=0;vis[s]=1;
    30     while(!q.empty())
    31     {
    32         int x=q.front();
    33         q.pop();vis[x]=0;
    34         for(int i=head[x];i!=-1;i=edge[i].next)
    35         {
    36             int y=edge[i].to;
    37             if(dis[y]>dis[x]+edge[i].val&&ddl[y]<=T&&ddl[x]<=T)
    38             {
    39                 dis[y]=dis[x]+edge[i].val;
    40                 if(!vis[y]) q.push(y),vis[y]=1;
    41             }
    42         }
    43     }
    44     if(dis[t]==inf) dis[t]=-1;
    45     return dis[t];
    46 }
    47 
    48 int main()
    49 {
    50     memset(head,-1,sizeof(head));
    51     scanf("%d%d",&n,&m);
    52     for(int i=0;i<n;i++) scanf("%d",&ddl[i]);
    53     for(int i=1;i<=m;i++)
    54     {
    55         int x=0,y=0,z=0;
    56         scanf("%d%d%d",&x,&y,&z);
    57         add(x,y,z);add(y,x,z);
    58     }
    59     scanf("%d",&Q);
    60     while(Q--)
    61     {
    62         int x=0,y=0,T=0;
    63         scanf("%d%d%d",&x,&y,&T);
    64         printf("%d
    ",spfa_ask(x,y,T));
    65     }
    66     return 0;
    67 } 
    View Code

    万万没想到,正解竟然是--floyd!

    其实看似繁琐的题目已经隐藏着真相--

    本题的数据范围n<=200,这对于最短路题目来说是十分超常友善的:)也正暗喻着本题floyd才是正解

    正解:

    我们考虑floyd的算法,本质是一个动态规划,最外层枚举中心点,注意到每次询问的时间有单调性,那么我们可以每次把两次询问间新建出的村庄的floyd跑好得出答案。

    看题解在这卡了很久,结果发现自己忽略了一个条件:输入村庄的修复时间也是有单调性的,有了这个条件一切不就顺理成章了嘛。

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 int n,m,Q,pos,limit;
     8 int ddl[300];
     9 int f[300][300];
    10 
    11 int main()
    12 {
    13     scanf("%d%d",&n,&m);
    14     memset(f,0x3f,sizeof(f));
    15     limit=f[3][3];
    16     for(int i=0;i<n;i++) scanf("%d",&ddl[i]),f[i][i]=0;
    17     for(int i=1;i<=m;i++)
    18     {
    19         int x=0,y=0,z=0;
    20         scanf("%d%d%d",&x,&y,&z);
    21         f[x][y]=z;f[y][x]=z;
    22     }
    23     scanf("%d",&Q);
    24     while(Q--)
    25     {
    26         int x=0,y=0,t=0;
    27         scanf("%d%d%d",&x,&y,&t);
    28         if(ddl[x]>t||ddl[y]>t)
    29         {
    30             printf("-1
    ");
    31             continue;
    32         }
    33         while(ddl[pos]<=t&&pos<n)
    34         {
    35             for(int i=0;i<n;i++)
    36                 for(int j=0;j<n;j++)
    37                     f[i][j]=min(f[i][j],f[i][pos]+f[pos][j]);
    38             pos++;
    39         }
    40         if(f[x][y]==limit)
    41         {
    42             printf("-1
    ");
    43             continue;
    44         }
    45         printf("%d
    ",f[x][y]);
    46     }
    47     return 0;
    48 } 
    View Code

    审题!审题!别丢条件!

  • 相关阅读:
    redis redis-cli 操作指令
    Apache 配置默认编码
    Apache 查找httpd.conf文件
    Apache 错误日志
    dataTable 自定义排序
    bootstrap select2 参数详解
    获取元素滚动条高度
    TP5 操作DB is null is not null 条件
    TP5 自带分页类的传参
    jquery 获取 file 表单 上传的文件名
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9490568.html
Copyright © 2020-2023  润新知