Description
Input
Output
Sample Input
3
2 2 4 3 5
2 1 2 3 6
2 1 2 2 2
5
3 4 4 2 8 5 3
1 5 8
4 1 6 4 10 2 7 5 2
0
2 2 5 1 5
0
Sample Output
3 2
3 10
题目大意:股票经纪人要在一群人中散布一个谣言,而谣言只能在亲密的人中传递,题目各处了人与人之间的关系及传递谣言所用的时间,要求程序给出应以那个人为起点,可以在最短的时间内让所有的人都得知这个谣言。
要注意从a到b传递的时间不一定等于从b到a的时间,如果没有方案能够让每一个人都知道谣言,则输出"disjoint"。(有关图的连通性,你懂得!但好像不用考虑这种情况一样能AC,只能说测试数据有点小水!)
题目数据的输入第一行为n,代表总人数,当n=0时结束程序,接着n行,第i+1行的第一个是一个整数t,表示第i个人与t个人的关系要好,接着有t对整数,每对的第一个数是j,表示i与j要好,第二个数是从i直接传递谣言到j所用的时间。
数据的输出是两个整数,第一个为选点的散布谣言的起点,第二个整数时所有人得知谣言的最短时间例如,对于数据1,可知如果从3开始播,则1,2得知谣言的时间都是2,所用的时间比从1,2开始传播所用的时间要短,故程序的输出时3 2;
解题思路:多源最短路Floyd()算法,详解见代码中的标注
具体代码: #include <stdio.h> #include <string.h> #define INF 0x3f3f3f3f #define Min(a,b) a>b?b:a int map[200][200]; int dist[200][200]; int N; void Floyd() { int i,j,k; for(k=1;k<=N;k++) for(i=1;i<=N;i++) for(j=1;j<=N;j++) dist[i][j]=Min(dist[i][j],dist[i][k]+dist[k][j]); } int main() { int n,i,j,v1,w; while(scanf("%d",&N) && N!=0) { memset(dist,INF,sizeof(dist)); for(i=0;i<=N;i++) dist[i][i]=0; for(i=1;i<=N;i++) { scanf("%d",&n); for(j=1;j<=n;j++) { scanf("%d%d",&v1,&w); dist[i][v1]=w;//单向传递,有向图 } } Floyd();//弗洛伊德多源最短路 int begin1,begin,time,tmin=INF; for(i=1;i<=N;i++) { time=0;//每次从i点开始传递时,时间初始化为 0 for(j=1;j<=N;j++)//从起点i开始查找i能够到达点的所需最长时间 if(dist[i][j]>time) { time=dist[i][j];//更新每次的从i作为起点得到的最大时间 begin1=i;//记录此时的起点 } if(time<tmin)//通过以上循环产生N个time,再求N个time中的最小值,并记录最小time时的begin { tmin=time; begin=begin1; } } if(tmin>=INF)//不能全部传达到 printf("disjoint\n"); else printf("%d %d\n",begin,tmin); } return 0; }