• URAL 1004 Sightseeing Trip(floyd求最小环+路径输出)


    https://vjudge.net/problem/URAL-1004

    题意:
    求路径最小的环(至少三个点),并且输出路径。

    思路:

    一开始INF开大了...无限wa,原来相加时会爆int...

    路径输出的算法是这样的:

        接下来就要看一看如何找出最短路径所行经的城市了,这里要用到另一个矩阵P,它的定义是这样的:p(ij)的值如果为p,就表示i到j的最短行经为i->...->p->j,也就是说p是i到j的最短行径中的j之前的最后一个城市。P矩阵的初值为p(ij)=i。有了这个矩阵之后,要找最短路径就轻而易举了。对于i到j而言找出p(ij),令为p,就知道了路径i->...->p->j;再去找p(ip),如果值为q,i到p的最短路径为i->...->q->p;再去找p(iq),如果值为r,i到q的最短路径为i->...->r->q;所以一再反复,到了某个p(it)的值为i时,就表示i到t的最短路径为i->t,就会的到答案了,i到j的最短行径为i->t->...->q->p->j。因为上述的算法是从终点到起点的顺序找出来的,所以输出的时候要把它倒过来。
         但是,如何动态的回填P矩阵的值呢?回想一下,当d(ij)>d(ik)+d(kj)时,就要让i到j的最短路径改为走i->...->k->...->j这一条路,但是d(kj)的值是已知的,换句话说,就是k->...->j这条路是已知的,所以k->...->j这条路上j的上一个城市(即p(kj))也是已知的,当然,因为要改走i->...->k->...->j这一条路,j的上一个城市正好是p(kj)。所以一旦发现d(ij)>d(ik)+d(kj),就把p(kj)存入p(ij)。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int INF = 1<<28;
     7 const int maxn = 100+10;
     8 
     9 int n,m;
    10 int ans,num;
    11 int g[maxn][maxn],dis[maxn][maxn];
    12 int path[maxn],pre[maxn][maxn];
    13 
    14 void floyd()
    15 {
    16     for(int k=1;k<=n;k++)
    17     {
    18         for(int i=1;i<k;i++)
    19         for(int j=i+1;j<k;j++)
    20         {
    21             int tmp = dis[i][j]+g[i][k]+g[k][j];  //从k点出发,回到k点
    22             if(tmp<ans)
    23             {
    24                 ans = tmp;
    25                 num = 0;
    26                 int p = j;
    27                 while(p!=i)
    28                 {
    29                     path[num++] = p; //记录路径
    30                     p = pre[i][p];
    31                 }
    32                 path[num++] = i;
    33                 path[num++] = k;
    34             }
    35         }
    36         for(int i=1;i<=n;i++)
    37         for(int j=1;j<=n;j++)
    38         {
    39             if(dis[i][j]>dis[i][k]+dis[k][j])
    40             {
    41                 dis[i][j] = dis[i][k] + dis[k][j];
    42                 pre[i][j] = pre[k][j];
    43             }
    44         }
    45     }
    46 }
    47 
    48 
    49 int main()
    50 {
    51    //freopen("in.txt","r",stdin);
    52     while(scanf("%d",&n) , n!=-1)
    53     {
    54         scanf("%d",&m);
    55         for(int i=1;i<=n;i++)
    56         for(int j=1;j<=n;j++)
    57         {
    58             if(i==j)  g[i][j]=dis[i][j]=0;
    59             else g[i][j]=dis[i][j]=INF;
    60             pre[i][j] = i;
    61         }
    62         for(int i=0;i<m;i++)
    63         {
    64             int u,v,w;
    65             scanf("%d%d%d",&u,&v,&w);
    66             if(dis[u][v]>w)
    67             {
    68                 g[u][v]=g[v][u]=dis[u][v]=dis[v][u]=w;
    69             }
    70         }
    71         ans = INF;
    72         floyd();
    73         if(ans==INF)  printf("No solution.
    ");
    74         else
    75         {
    76             for(int i=0;i<num;i++)  printf("%d%c",path[i],i==num-1?'
    ':' ');
    77         }
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    Nhibernate多表查询解决办法
    Nhibernate compositeid class must override Equals()解决办法
    SQLSERVER2005安装说明
    IList转化为Dataset C#
    Named SQL queries
    把object转换成DataSet,进行数据绑定
    使用Lucene检索文档中的关键字
    使用代理为业务操作添加安全检测
    mongodb副本集架构搭建
    Java生成中文验证码
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7866789.html
Copyright © 2020-2023  润新知