zoukankan      html  css  js  c++  java
  • [floyd][usaco.09.DEC.][jzyzoj1218][过路费]——floyd新姿势get

      这道题并没有1A,因为读入邻接矩阵的时候忘了处理重边。。。下面给出题面:

      

      最初看的时候以为纯粹的floyd是可以用的,然而发现并不可以,因为无法查找遍历的最大点,这时候需要转变思想:当你遍历i,j,k时,如何保证权值最大的点就在这三个点之间?我们是不是能将点重组一遍,让所有点按照权值大小排列呢?

      这样思路就有了:

      如果k从大到小排列的话,不能保证权值在i,j,k之间,因为更新过路径之后权值最大的点已经包含在路径中了。

      如果k从小到大排列的话,每次更新最短路,权值最大的点都会在i,j,k之间。

      所以我们可以按照这个思路,记录每个点的下标及权值,然后按照权值从小到大排序,所得到的序列就是k应该查找的顺序。

      另外处理边的时候需要将最短路与最短路加上最大点权值分开处理。

      代码如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 struct points{
     7     int v,p;
     8 }point[260];//v为点的值,p为点的坐标
     9 int a[260][260],n,m,k,c[260][260],cow[260];
    10 bool mycmp(points x,points y)
    11 {return x.v<y.v;}
    12 void init()
    13 {
    14     scanf("%d%d%d",&n,&m,&k);
    15     memset(a,0x3f,sizeof(a));
    16     for (int i=1;i<=n;i++)
    17     {
    18         scanf("%d",&point[i].v);
    19         a[i][i]=0;    c[i][i]=point[i].v;//点到自身的距离处理,c为边+最大点权值的值,a为边值
    20         cow[i]=point[i].v;//另记录每个点的权值,方便查找
    21         point[i].p=i;
    22     }
    23     int x,y,v;
    24     for (int i=1;i<=m;i++)
    25     {
    26         scanf("%d%d%d",&x,&y,&v);
    27         a[x][y]=min(a[x][y],v);//处理重边
    28         a[y][x]=a[x][y];
    29     }
    30     sort(point+1,point+1+n,mycmp);//将点按照从小到大排序
    31 }
    32 
    33 void floyd()
    34 {
    35     for (int x=1;x<=n;x++)
    36     {
    37         int k=point[x].p;
    38         for (int i=1;i<=n;i++)
    39             for (int j=1;j<=n;j++)
    40             {
    41                 a[i][j]=a[j][i]=min(a[i][k]+a[k][j],a[i][j]);//更新最短路
    42                 c[i][j]=c[j][i]=min(c[i][j],a[i][j]+max(max(cow[i],cow[j]),cow[k]));//将当前求得最小值与最短路加上最大权值进行比较并更新
    43             }
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     freopen("add.in","r",stdin);
    50     freopen("add.out","w",stdout);
    51     memset(c,0x3f,sizeof(c));
    52     init();
    53     floyd();
    54     int x,y;
    55     for (int i=1;i<=k;i++)
    56     {
    57         scanf("%d%d",&x,&y);
    58         printf("%d
    ",c[x][y]);
    59     }
    60     return 0;
    61 }
    AC代码

      这道题对于floyd的理解具有巨大帮助。

  • 相关阅读:
    C# 基础练习题
    WinForm中实现播放mp3 、mp4文件
    C语言实现的水仙花数
    【转】.net 经典面试题
    vipspa实现前端路由
    spring定时任务<task:scheduled-tasks>的问题
    MongoDB中$month和$dayOfMonth的坑
    SpringMVC中MultipartFile参数问题
    IllegalStateException : Web app root system property already set to different value问题详解
    jsoup简单的爬取网页数据
  • 原文地址:https://www.cnblogs.com/hinanawitenshi/p/6558250.html
Copyright © 2011-2022 走看看