hdu1599(floyd算法讲解)

Description

杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。 
 

Input

第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数。 
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。
 

Output

对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出"It's impossible.".
 

Sample Input

     
     
     
     
3 3 1 2 1 2 3 1 1 3 1 3 3 1 2 1 1 2 3 2 3 1
 

Sample Output

     
     
     
     
3 It's impossible.


简单的说floyd算法就是下面这段代码的延伸:

for(int k=1;k<=n;k++)
     for(int i=1;i<=n;i++)
         for(int j=1;j<=n;j++)
            d[i][j]=min(d[i][k]+d[k][j],d[i][j]);

(1)算法思想原理:

     Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)

      从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

(2).算法描述:

a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。   

b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。


而对于这题,至少经过俩景区,想想看?这个俩景区有什么用?!!!

如果只是经过一个景区,那么与两景区唯一不同的一种可能情况就是经过一个景区可能就是往返,因此!!!连不成环~~~~

那么!接下来这题不久将问题转化成了与经过俩景区完全无关的成环的最小权值问题吗?这个思想搞清楚了再去看代码会清晰很多!!

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[110][110],d[110][110];
const int maxn=100000000;
void init(int n)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        a[i][j]=maxn,d[i][j]=maxn;
}

int main()
{
    int m,n;
    while(~scanf("%d%d",&n,&m))
    {
        init(n);
        for(int i=0;i<m;i++)
        {
            int a1,a2,ww;
            scanf("%d%d%d",&a1,&a2,&ww);
           if(a[a1][a2]>ww)
           a[a1][a2]=a[a2][a1]=d[a1][a2]=d[a2][a1]=ww;
        }
        int min0=maxn;
        for(int k=1;k<=n;k++)
            {
                for(int i=1;i<k;i++)
                    for(int j=i+1;j<k;j++)
                        min0=min(min0,d[i][j]+a[i][k]+a[k][j]);
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                        d[i][j]=min(d[i][k]+d[k][j],d[i][j]);
            }
        if(min0>=maxn)
        printf("It's impossible.\n");
        else printf("%d\n",min0);
    }
    return 0;
}

你可能感兴趣的:(ACM,图,大一)