zoukankan      html  css  js  c++  java
  • vijos 观光旅游 最小环fl 呆详看

    背景

    湖南师大附中成为百年名校之后,每年要接待大批的游客前来参观。学校认为大力发展旅游业,可以带来一笔可观的收入。

    描述

    学校里面有N个景点。两个景点之间可能直接有道路相连,用Dist[I,J]表示它的长度;否则它们之间没有直接的道路相连。这里所说的道路是没有规定方向的,也就是说,如果从I到J有直接的道路,那么从J到I也有,并且长度与之相等。学校规定:每个游客的旅游线路只能是一个回路(好霸道的规定)。也就是说,游客可以任取一个景点出发,依次经过若干个景点,最终回到起点。一天,Xiaomengxian决定到湖南师大附中旅游。由于他实在已经很累了,于是他决定尽量少走一些路。于是他想请你——一个优秀的程序员——帮他求出最优的路线。怎么样,不是很难吧?(摘自《郁闷的出纳员》)

    格式

    输入格式

    对于每组数据:
    第一行有两个正整数N,M,分别表示学校的景点个数和有多少对景点之间直接有边相连。(N<=100,M<=10000)
    以下M行,每行三个正整数,分别表示一条道路的两端的编号,以及这条道路的长度。

    输出格式

    对于每组数据,输出一行:
    如果该回路存在,则输出一个正整数,表示该回路的总长度;否则输出“No solution.”(不要输出引号)

    样例1

    样例输入1

    5 7
    1 4 1
    1 3 300
    3 1 10
    1 2 16
    2 3 100
    2 5 15
    5 3 20
    4 3
    1 2 10
    1 3 20
    1 4 30
    

    样例输出1

    61
    No solution.
    

    限制

    各个测试点1s

    by  http://wenku.baidu.com/view/c6382a41a8956bec0975e3c0.html?from=related
          http://blog.csdn.net/youngyangyang04/article/details/7054931

    典型的最小环问题
    因为n很小可以直接Floyd求最小环
    注意最小环ans更新的位置
    每次枚举k为下家更新点
    应该先尝试更新ans再更新i,j之间的最短路
    我们用g[i][j]来记录i,j之间最短路径
    而w[i][j]用来保存i,j之间的原始路径长度
    因为我们知道i,j要构成一个最小环
    肯定要有两条路可走
    1.直接从i到j。
    2.从i经过某个中途点k到达j
    即对于每一个k 我们先尝试从这个k点对于所有的i,j点能不能得到最小环
    然后我们再用这个k点尝试更新路径
    该算法的证明:
    一个环中的最大结点为K(编号最大),与其相连的两个点为i,j ,
    这个环的最短长度为: g[i][k] + g[k][j] + i到j的路径中所有结点编号都不大于k的最短路径长度,
    根据floyd的原理,在最外层循环做一个k-1次之后,
    g[i][j] 则代表了i到j的路径中所有结点的编号都不大于k的最短路径。
    所以我们枚举的i,j要有
    1<=i<k,i<j<k
    再换一种说法吧
    比普通Floyd多出来的部分,主要利用到的原理是当处理到k时,
    所有以1 到k - 1为中间结点的最短路径都已经确定,
    则这时候的环为(i到j(1 < i, j <= k - 1)的最短路径) + 边(i, k) + 边(k, j)
    遍历所有的i, j找到上述式子的最小值即位k下的最小代价环  
    */
    /*
    路径的求法:
    用一个pre[i][j]记录j前面的一个顶点, 初始化为i,当出现需要更新的时候则将pre[i][j] = pre[k][j];
    若i== j的时候则表示找全了路径,最后将k点加入路径中
    核心代码:
    While(i != j)
    {  
        if (i != j)
        {  
            Path[len++] = j;
            J = pre[i][j];
        }  
         Path[len++] = i;
    }

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    const int INF=1e8;
    int w[102][102],g[102][102];
    int n,e;
    
    void init()
    {
        int x,y,v;
        for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    w[i][j]=g[i][j]=INF;
        for(int i=1;i<=e;i++)
        {
            scanf("%d%d%d",&x,&y,&v);
            w[x][y]=w[y][x]=g[x][y]=g[y][x]=v;
        }
    }
    
    void work()
    {
        int ans=INF;
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<k;i++)//最小环
                for(int j=i+1;j<k;j++)//为了避免一条边计算两次并且i == j时因为权重会出错 
                    ans=min(ans,g[i][j]+w[i][k]+w[k][j]);
            for(int i=1;i<=n;i++)//Floyd
                for(int j=1;j<=n;j++)
                    if(i!=j)
                        g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
        }
        if(ans==INF)
            printf("No solution.
    ");
        else
            printf("%d
    ",ans);
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&e)!=EOF)
        {
            init();
            work();
        }
    }
  • 相关阅读:
    [zz][openstack swift]0 swift介绍
    [zz]/usr、/var和/etc目录
    [zz]使用 watchdog 构建高可用性的 Linux 系统及应用
    [zz]sheep dog的readme
    [zz] Consistent Hashing Ring
    [zz]为什么这些死脑筋们在用 VI ?
    libvirt 网络
    [zz]libcapng
    libvirt 创建的文件
    电商购物网站如何调用第三方支付平台(支付宝,财付通,盛付通等)
  • 原文地址:https://www.cnblogs.com/lyqlyq/p/7123286.html
Copyright © 2011-2022 走看看