2018多校第三场 hdu6331 M :Walking Plan

题目链接 hdu6331

自我吐槽,这场多校大失败,开局签到因输入输出格式写错,wa了3发。队友C题wa了1个小时,还硬说自己写的没错,结果我随便造了个小数据,他都没跑对。然后跑对了后又进入了无限的卡常之中,幸好最后卡过去了。

G题我头铁写了个单侧凸壳,不对输入数据判重,而是在加入凸壳时判断,结果wa到比赛结束,进而导致I没时间写。M题开局看错题意直接丢了。最后从30多名掉到了150。这大概就是菜得安详吧 ̄ω ̄=

题意

给定n个点m条有向边,q次查询,每次查询问走至少k条边的,s到t的最短路径的长度,边可以重复走。

q=100000,n=50,m<=10000,k<=10000..

这题用矩阵快速幂啥的复杂度爆炸

细节

1.首先最基本的,要先对边去重留下最短边。

2.这里有个细节要注意一下,在某些情况下 s 到t距离,只有在走过的边数达到某个周期后才有解。

比如n个点组成一条有向环,则1到2距离只有在走过数边数k=1,n+1,2n+1  。周期也就是环的长度。

所以查询k时,答案的路径边数范围会在k到n+k之间。

3.任意两点的最短距离的边数小于n

预处理

首先预处理两个数组。g[k][s][t] 代表恰好走k条边后s到t的最短路径。

k=1,2,……10000.

这个用Floyd跑全部数据复杂度要k*n*n*n=12.5亿=GG。  这显然是不行的,所以只能分块,我取块长为100,即只让k=1,2,3,……100。但相邻二维数组之间间隔100条边。则复杂降低至1250万。

接着就是怎么处理块内了。

dis[k][s][t] 代表走大于等于k条边后s到t的最短路径。

k=1,2,……100 。

 这个处理方式时先用floyd跑到k=200, 再逆向for 令dis[k][s][t]=min(dis[k][s][t],dis[k+1][s][t])这样就能保证在k=1,2,3……100时答案是正确的。

因为大于等于k的最坏情况,就是从s到达了点z,接着还要跑(z,t)之间的最短路才能到达t. 而最短路D的边数最多就n-1。 其实更新n项后就一定就正确了。所以溢出100项,只是写的顺手。

查询

对于k<=100的查询我们可以直接用dis数组回答复杂度O(1)

对于k>100的查询,令 k=q*100+r   其中1<=r<=100

则答案就是min(g[q][s][z]+dis[r][z][t])   。其中z是我们枚举的中间点。 这样就能保证查询到的答案是大于等于k的,且答案是正确的。单次查询复杂度O(n)

 

AC代码

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 using namespace std;
  6 int dis[202][52][52];
  7 int g[102][52][52];
  8 int INF=1e9,n;
  9 int get(int s,int t,int k)
 10 {
 11     if(k<=100)
 12     {
 13         return dis[k][s][t];
 14     }
 15     else
 16     {
 17         register int i,q,r,ans=INF;
 18 
 19         q=(k-1)/100;
 20         r=k-100*q;
 21         //printf("%d %d \n",q,r);
 22         for(i=1; i<=n; i++)
 23         {
 24             ans=min(ans,dis[r][s][i]+g[q][i][t]);
 25         }
 26         return ans;
 27     }
 28 }
 29 int main()
 30 {
 31     int m,t,x,y,w,q,ans;
 32     register int i,j,k,l;
 33     scanf("%d",&t);
 34     while(t--)
 35     {
 36         scanf("%d%d",&n,&m);
 37         memset(dis,63,sizeof(dis));
 38         memset(g,63,sizeof(g));
 39         INF=dis[0][0][0];
 40         //   printf("%d\n",INF);
 41         for(i=1; i<=n; i++)
 42         {
 43             for(j=1; j<=n; j++)
 44             {
 45                 dis[1][i][j]=INF;
 46             }
 47         }
 48         while(m--)
 49 
 50         {
 51             scanf("%d%d%d",&x,&y,&w);
 52             dis[1][x][y]=min(dis[1][x][y],w);
 53         }
 54         for(i=2; i<=200; i++)
 55         {
 56             for(j=1; j<=n; j++)
 57             {
 58                 for(k=1; k<=n; k++)
 59                 {
 60                     for(l=1; l<=n; l++)
 61                     {
 62                         dis[i][j][k]=min( dis[i][j][k],dis[i-1][j][l]+dis[1][l][k]);
 63                     }
 64                 }
 65             }
 66         }
 67         for(i=1; i<=n; i++)
 68         {
 69             for(j=1; j<=n; j++)
 70             {
 71                 g[1][i][j]=dis[100][i][j];
 72             }
 73         }
 74         for(i=2; i<=100; i++)
 75         {
 76             for(j=1; j<=n; j++)
 77             {
 78                 for(k=1; k<=n; k++)
 79                 {
 80                     for(l=1; l<=n; l++)
 81                     {
 82                         g[i][j][k]=min( g[i][j][k],g[i-1][j][l]+g[1][l][k]);
 83                     }
 84                 }
 85             }
 86         }
 87         for(i=199; i>=1; i--)
 88         {
 89             for(j=1; j<=n; j++)
 90             {
 91                 for(k=1; k<=n; k++)
 92                 {
 93                     dis[i][j][k]=min( dis[i][j][k],dis[i+1][j][k]);
 94                 }
 95             }
 96         }
 97         scanf("%d",&q);
 98         while(q--)
 99         {
100             scanf("%d%d%d",&x,&y,&k);
101             ans=get(x,y,k);
102             if(ans<=INF/10)
103             {
104                 printf("%d\n",ans);
105             }
106             else
107             {
108                 puts("-1");
109             }
110         }
111     }
112 
113     return 0;
114 }
HDU6331

话说我写的这么暴力,在ac代码里居然不算很慢的︿( ̄︶ ̄)︿

 

posted @ 2018-07-31 10:32  强势围观  阅读(866)  评论(0编辑  收藏  举报