URAL1004 Sightseeing Trip

这个题最开始看标签是最短路,,当时就想的是裸的那啥(d...tra什么玩意),使劲使劲读题才觉得是最小环的问题,,,,,这个也不会呀咱,,,,,也不知道有没有模板,,,所以我就先学习了一下Floyd求最小环。。。。。。。。先讲这个再看题意吧。。哎


这个算法其实,,,,不难理解,,就是A到B的最短路线,,要么是dis(A,B),要么是dis(A,X)+dis(X,B)..就是中间的一个点,,,,,,应该可以算是动态规划的一种情况了,,,,,要说代码,,就是这样的。。。。

for ( k=1; k<=节点个数;++k){
    for (i=1;i<=节点个数; ++i ){
        for ( j = 1; j <= 节点个数; ++j ){
            if ( dis[i][k] + dis[k][j] < dis[i][j] ){
                dis[i][j] = dis[i][k] + dis[k][j]; //找到更短路径
            }
        }
    }
}

都不好意思打啊有木有。。。。。。找到所有dis[i][j]的最小值。。。


再说题意。。。找到起点与终点相同的最短路线,,,然后什么十字路口的烦死了有木有啊!!那是什么鬼,,,,,我就把它无视掉了。。。。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

int d[101][101];  //储存dp
int q[101][101];  //记录长度
int p[101][101];  //之前的路
int s[101];       //answer

int main()
{
    int m,n;
    while(scanf("%d",&n)&&n!=-1)
    {
        scanf("%d",&m);
        int i,j,k;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                d[i][j]=q[i][j]=9999999;  //全部初始化(不通就是正无穷的大小)
            }
            d[i][i]=q[i][i]=0;  //自己和自己当然零距离
        }
        memset(p,-1,sizeof(p));
        for(i=0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w); u--,v--;        //好放到数组里,,最后加1就好
            if(d[u][v]>w&&u!=v) d[u][v]=d[v][u]=q[u][v]=q[v][u]=w;    //如果有一次给的距离比之前的要小,由于都是双行道所以果断舍弃之前的啊
            p[u][v]=v; p[v][u]=u;          //u到v的尽头是v,v到u的尽头是u
        }
        int ans=9999999,ll,pl;
        for(k=0;k<n;k++)
        {
            for(i=0;i<n;i++)     //这个是最小环的判定。。。。。
            {
                for(j=0;j<n;j++)
                {
                    if(d[i][k]&&d[k][j]&&d[i][k]!=9999999&&d[k][j]!=9999999&&i!=j)    //如果i,j,k不是一个点而且通的话(没有那两个!=9999999反而快了。。。)
                    {
                        int temp=d[k][i]+q[i][j]+d[j][k]; //计算一个环的距离,,起点终点都是k
                        if(temp<ans)  //不仅要更新数值更要更新路径。。。。
                        {
                            ans=temp;
                            s[0]=k;
                            ll=0,pl=i; //先是等于从k出去的第一条路
                            while(pl!=-1)
                            {
                                s[++ll]=pl;  //记录下来
                                pl=p[pl][j];  //找下一条路。。。直到前面没有路(回到原点)
                            }
                        }
                    }
                }
            }
            for (int i = 0; i < n; i++)  //用的就是那个算法找到ij间的最短距离
   {
    for (int j = 0; j < n; j++)
    {
     if (q[i][j] > q[i][k] + q[k][j])
     {
      q[i][j] = q[i][k] + q[k][j];
      p[i][j] = p[i][k]; //让人在记录的时候不至于迷路
     }
    }
   }

        }
        if (ans == 9999999) printf("No solution.\n");
  else
  {
   for (int i = 0; i < ll; i++)
    printf("%d ", s[i] + 1);
   printf("%d\n", s[ll] + 1);
  }
    }
 return 0;

}

另::我要上传的时候突然发现。。。。Dij..tra也是可以的!!!第一次先找到i到j的min,然后去掉这种情况再找一次就好!!

总是还是像模板题吧。。。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值