HOJ 1113 Stockbroker Grapevine (Floyd最短路)

题意:谣言在n个人之间传播,谣言从一个人传给另一个人需要一定时间(是有向图)。问谣言从哪个人开始传,传遍所有人所用时间最短(这里的时间指的是,传到最后一个人时所用的时间)。输出这个人的编号,及所需要时间。


分析:Dijkstra是用来求单源最短路的,而这里起点不确定。采用Floyd算法先对图进行收缩,O(n^3)的复杂度。对每个点,找到这个点做源点时,谣言传遍所有人所需要的“时间”,遍历所有点,找到最短的那个“时间”,复杂度为O(n^2)。


对于floyd算法:

算法描述:
(1) 用数组dis[i][j]来记录i,j之间的最短距离。初始化dis[i][j],若i=j则dis[i][j]=0,
若i,j之间有边连接则dis[i][j]的值为该边的权值,否则dis[i][j]的值为无穷大 。
(2) 对所有的k值从1到n,修正任意两点之间的最短距离,计算dis[i][k]+dis[k][j]的值,
若小于dis[i][j],则dis[i][j]= dis[i][k]+dis[k][j],否则dis[i][j]的值不变。

void Floyd(int dis[n+1][n+1],int n)
{
	int i,j,k;
	for(k=1;k<=n;k++)
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				if(dis[i][k]+dis[k][j]<dis[i][j])
		                {
					dis[i][j] = dis[i][k]+dis[k][j];
                                }

}

复杂度为O(n^3)



#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x7fffffff
using namespace std;
int map[105][105];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF && n) {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                map[i][j]=INF;       //这里用memset(map,INF,sizeof(map))的话,map总是被初始化成-1,求大神解释这是为什么?
            }
        }
        for(int i=0; i<n; i++)map[i][i]=0;
        for(int i=0; i<n; i++) {
            int t;
            scanf("%d",&t);
            for(int j=0; j<t; j++) {
                int p;
                int d;
                scanf("%d %d",&p,&d);
                map[i][p-1]=d;
            }
        }

        for ( int k = 0; k < n; ++k ) {          //floyd对图进行收缩,map[i][j]储存的内容变成了i,j间最短的距离
            for ( int i = 0; i <n; ++i ) {
                for ( int j = 0; j <n; ++j ) {
                    if(map[i][k]!=INF && map[k][j]!=INF) {
                        if ( map[i][k] + map[k][j] < map[i][j] ) {
                            // 找到更短路径
                            map[i][j] = map[i][k] + map[k][j];
                        }
                    }
                }
            }
        }
        
        int minn,start;
        minn=INF;
        for(int i=0; i<n; i++) {
            int maxn=0;
            for(int j=0; j<n; j++) {
                maxn=max(map[i][j],maxn);  //以i为源点时,所需要消耗的“时间”(即传播到最远的那个人所需要时间)。					   					   //因为前面已经对图进行了收缩,map[i][j]储存的已经是i到j的最短距离了
            }
            if(minn>maxn) {   //找到用时最短的那个源点
                minn=maxn;
                start=i;
            }
        }
        if(minn==INF)printf("disjoint\n");
        else {
            printf("%d %d\n",start+1,minn);
        }

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值