首先想到的是Dijkstra算法,但觉得速度可能会很慢,于是上网大概搜了一下,看到别人说这道题用Floyd算法,虽然听过这个算法,但没用过,于是先学习了Floyd算法,然后顺利解决了该题。
题目大意:(题目翻译转载自http://blog.youkuaiyun.com/lyy289065406/article/details/6645856)
众所周知,证券经纪业对谣言非常敏感。您需要想出股票经纪人中传播假情报的方法,让您的雇主在股票市场的占据优势。为了获得最大的效果,你必须蔓延最快的方式谣言。
不幸的是你,股票经纪人信息只信任他们的“可靠来源”,这意味着你在你传播谣言之前必须考虑到他们的接触结构。它需要特定股票经纪人和一定的时间把谣言传递给他的每一位同事。你的任务将是写一个程序,告诉您选择哪一个股票经纪人作为谣言的出发点和所花费多少时间将谣言扩散到整个社会的股票经纪人。这一期限是衡量过去的人收到信息所需的时间。
输入
你的程序包含多组股票经纪人的输入数据。每组以股票经纪人的人数开始。接下来的几行是每个经纪人与其他人接触的一些信息,包括这些人都是谁,以及将讯息传达到他们所需的时间。每个经纪人与其他人接触信息的格式如下:开头的第一个数表示共有n个联系人,接下来就有n对整数。每对整数列出的第一个数字指的是一个联系人(例如,一个'1'是指编号1的人),其次是在传递一个信息给那个人时所采取分钟的时间。没有特殊的标点符号或空格规则。
每个人的编号为1至经纪人数目。所花费的传递时间是从1到10分钟(含10分种)。股票经纪的人数范围是从1到100。当输入股票经纪人的人数为0时,程序终止。
输出
在对于每一组数据,你的程序必须输出一行,包括的信息有传输速度最快的人,以及在最后一个人收到消息后,所总共使用的时间(整数分钟计算)。
你的程序可能会收到的一些关系会排除一些人,也就是有些人可能无法访问。如果你的程序检测到这样一个破碎的网络,只需输出消息“disjoint”。请注意,所花费的时间是从A传递消息到B,B传递信息到A不一定是花费同样的传递时间,但此类传播也是可能的。
#include<stdio.h>
int g[101][101]; //保存图的数据
int d[101][101][101];
int infinite=~(1<<31);
void init_matrix(int a[101][101], int n)
{
int i,j;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
a[i][j]=infinite;
}
int min(int a, int b)
{
if(b<0) b=infinite;
return a<b ? a : b;
}
void floyd(int n)
{
int i,j,k;
for(k=1; k<=n; k++)
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
d[k][i][j] = min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j]);//注意第二个参数有可能溢出变为负数
}
}
int main()
{
int n,i,j,contact_num, contact, time;
int start, min_time, max;
scanf("%d", &n); //读入股票经纪人数目
while(n)
{
//初始化矩阵
init_matrix(g, n);
init_matrix(d[0], n);
//读入数据
for(i=1; i<=n; i++)
{
scanf("%d", &contact_num); //读入该经纪人的联系人数
while(contact_num--)
{
scanf("%d %d", &contact, &time); //读入该联系人的编号和传输信息的时间
g[i][contact]=time;
d[0][i][contact]=time;
}
g[i][i]=0;
d[0][i][i]=0;
}
//计算矩阵中两点之间的最短距离
floyd(n);
//找出最短路径的起始点和需要花费的时间
min_time=infinite;
for(i=1; i<=n; i++) //从i开始传播
{
max=-infinite;
for(j=1; j<=n; j++) //找出从i开始传播到整个网络的最大时间
{
if(d[n][i][j]>max) max=d[n][i][j];
}
if(max==infinite) continue; //存在从i开始不可到达的点
if(max<min_time)
{
min_time=max;
start=i;
}
}
if(min_time==infinite) printf("disjoint\n");
else printf("%d %d\n", start, min_time);
scanf("%d", &n);
}
return 0;
}
可将将d[101][101][101]压缩至d[2][101][101]
#include<stdio.h>
int g[101][101]; //保存图的数据
int d[2][101][101];
int infinite=~(1<<31);
void init_matrix(int n)
{
int i,j;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
g[i][j]=infinite;
d[0][i][j]=infinite;
}
}
int min(int a, int b)
{
if(b<0) b=infinite;
return a<b ? a : b;
}
void floyd(int n)
{
int i,j,k,k1,k2;
for(k=1; k<=n; k++)
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
k1 = k%2;
k2=(k1+1)%2;
d[k1][i][j] = min(d[k2][i][j], d[k2][i][k]+d[k2][k][j]);//注意第二个参数有可能溢出变为负数
}
}
int main()
{
int n,i,j,k,contact_num, contact, time;
int start, min_time, max;
scanf("%d", &n); //读入股票经纪人数目
while(n)
{
//初始化矩阵
init_matrix(n);
//读入数据
for(i=1; i<=n; i++)
{
scanf("%d", &contact_num); //读入该经纪人的联系人数
while(contact_num--)
{
scanf("%d %d", &contact, &time); //读入该联系人的编号和传输信息的时间
g[i][contact]=time;
d[0][i][contact]=time;
}
g[i][i]=0;
d[0][i][i]=0;
}
//计算矩阵中两点之间的最短距离
floyd(n);
//找出最短路径的起始点和需要花费的时间
min_time=infinite;
k=n%2;
for(i=1; i<=n; i++) //从i开始传播
{
max=-infinite;
for(j=1; j<=n; j++) //找出从i开始传播到整个网络的最大时间
{
if(d[k][i][j]>max) max=d[k][i][j];
}
if(max==infinite) continue; //存在从i开始不可到达的点
if(max<min_time)
{
min_time=max;
start=i;
}
}
if(min_time==infinite) printf("disjoint\n");
else printf("%d %d\n", start, min_time);
scanf("%d", &n);
}
return 0;
}