Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 24440 | Accepted: 13443 |
Description
Unfortunately for you, stockbrokers only trust information coming from their "Trusted sources" This means you have to take into account the structure of their contacts when starting a rumour. It takes a certain amount of time for a specific stockbroker to pass the rumour on to each of his colleagues. Your task will be to write a program that tells you which stockbroker to choose as your starting point for the rumour, as well as the time it will take for the rumour to spread throughout the stockbroker community. This duration is measured as the time needed for the last person to receive the information.
Input
Each person is numbered 1 through to the number of stockbrokers. The time taken to pass the message on will be between 1 and 10 minutes (inclusive), and the number of contacts will range between 0 and one less than the number of stockbrokers. The number of stockbrokers will range from 1 to 100. The input is terminated by a set of stockbrokers containing 0 (zero) people.
Output
It is possible that your program will receive a network of connections that excludes some persons, i.e. some people may be unreachable. If your program detects such a broken network, simply output the message "disjoint". Note that the time taken to pass the message from person A to person B is not necessarily the same as the time taken to pass it from B to A, if such transmission is possible at all.
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 題目大一(相當的難懂):
首先,題目可能有多組測試數據,每個測試數據的第一行爲經紀人數量N(當N=0時,輸入數據結束),然後接下來N行描述第i(1<=i<=N)個經紀人與其他經紀人的關係 (教你如何畫圖)。每行開頭數字M爲該行對應的經紀人有多少個經紀人朋友(該節點的出度,可以爲0),然後緊接着M對整數,每對整數表示成a,b,則表明該經紀人向第a 個經紀人傳遞信息需要b單位時間(即第i號結點到第a號結點的孤長爲b),整張圖爲有向圖,即弧Vij 可能不等於弧Vji(數據很明顯,這裏是廢話)。 當構圖完畢後,求當從該圖中某點出發,將“消息”傳播到整個經紀人網絡的最小時間,輸出這個經紀人號和最小時間。 最小時間的判定方式爲——從這個經紀人(結點)出發,整個經紀人網絡中最後一個人接到消息的時間。 如果有一個或一個以上經紀人無論如何無法收到消息,輸出“disjoint”(有關圖的連通性,你們懂得,但據其他同學說,POJ測試數據中不會有, 就是說,你不判定,一樣能過,題目數據夠水的)。
思路:由於“將“消息”傳播到整個經紀人網絡的最小時間”是按最玩的那個人收到的時間,所以可以轉化爲,以每個i點位源點作單源路徑,
記d[i]爲求源點i到其他點的距離的最大值,
求min(d[i]),和i,其中1<=i<=n;
方法一:依照思路很容想到對每個節點用一次單源最短路算法,所有源點中所到其他點的其最大值的最小值,時間複雜度爲O(n^3);
/*
@author : liuwen
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cmath>
using namespace std;
const int maxn=105;
const int inf=0x5fffffff;
int Map[maxn][maxn],dist[maxn],p[maxn];
int n,m;
void initial_map() //初始化圖,用鄰接矩陣建圖,空間複雜度爲O(n^2)
{
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) Map[i][j]=0;
else Map[i][j]=inf;
}
}
for(int i=1;i<=n;i++){
int t,v,w;
scanf("%d",&t);
while(t--){
scanf("%d%d",&v,&w);
Map[i][v]=min(Map[i][v],w);
}
}
}
void Dijkstra(int s) //以s爲源點的單源最短路
{
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++){
dist[i]=Map[s][i];
}
dist[s]=0;
p[s]=1;
int i,j,k,Min;
for(i=1;i<=n-1;i++){
Min=inf,k=0;
for(j=1;j<=n;j++){
if(!p[j]&&Min>dist[j]){ //我艹,把符號寫反了,3wa
Min=dist[j];
k=j;
}
}
if(k==0) return; //如果Vb(還沒有選擇的點集合中)中點都不可到達,則可以直接退出
p[k]=1;
for(j=1;j<=n;j++){ //鬆弛操作,更新
if(!p[j]&&Map[k][j]!=inf&&dist[j]>dist[k]+Map[k][j]){
dist[j]=dist[k]+Map[k][j];
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)==1){
if(n==0) break;
initial_map();
int maxLength=-inf,minTrans=inf,fastTrans=1;
for(int i=1;i<=n;i++){
maxLength=-inf;
Dijkstra(i); //以每個節點爲源點的單源最短路
for(int j=1;j<=n;j++){
if(dist[j]>maxLength){
maxLength=dist[j];
}
}
if(maxLength<minTrans){
fastTrans=i;
minTrans=maxLength;
}
}
if(minTrans==inf){ //不可以達到
printf("disjoint\n");
}else{
printf("%d %d\n",fastTrans,minTrans);
}
}
return 0;
}
第二種方法:floly多源路徑的最短路問題,複雜度爲O(n^3)floyd原理說明
其思想爲動態規劃的思想:
<i,j>的最短距離 =min{ <i,j>的距離,<i,k>+<k,j>(經過一箇中間點)距離和}
即:Map[i][j]=min(Map[i][j],Map[i][k]+Map[k][j]);
/*
@author : liuwen
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cmath>
using namespace std;
const int maxn=105;
const int inf=0x1fffffff; //一開始inf開的太大,Map[i][j]=min(Map[i][j],Map[i][k]+Map[k][j]);算加法的時候溢出了T_T
int Map[maxn][maxn],n;
void initial_map()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++){
if(i==j) Map[i][j]=0;
else Map[i][j]=inf;
}
}
for(int i=1;i<=n;i++){
int t,v,w;
scanf("%d",&t);
while(t--){
scanf("%d%d",&v,&w);
Map[i][v]=min(Map[i][v],w);
}
}
}
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
Map[i][j]=min(Map[i][j],Map[i][k]+Map[k][j]);//一開始inf開的太大,"Map[i][k]+Map[k][j]"加法溢出T_T,的了變成負數。。樣例都沒過。
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)==1){
if(n==0) break;
initial_map();
floyd();
int fastTrans=1,maxlength=-inf,minTrans=inf;
for(int i=1;i<=n;i++){
maxlength=-inf;
for(int j=1;j<=n;j++){
maxlength=max(maxlength,Map[i][j]);
}
if(maxlength<minTrans){
minTrans=maxlength;
fastTrans=i;
}
}
if(minTrans==inf) printf("disjoint\n");
else printf("%d %d\n",fastTrans,minTrans);
}
return 0;
}