poj1125 POJ 1125 Stockbroker Grapevine(兩種方法Dijkstra或者floyd)

Stockbroker Grapevine
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 24440   Accepted: 13443

Description

Stockbrokers are known to overreact to rumours. You have been contracted to develop a method of spreading disinformation amongst the stockbrokers to give your employer the tactical edge in the stock market. For maximum effect, you have to spread the rumours in the fastest possible way.

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

Your program will input data for different sets of stockbrokers. Each set starts with a line with the number of stockbrokers. Following this is a line for each stockbroker which contains the number of people who they have contact with, who these people are, and the time taken for them to pass the message to each person. The format of each stockbroker line is as follows: The line starts with the number of contacts (n), followed by n pairs of integers, one pair for each contact. Each pair lists first a number referring to the contact (e.g. a '1' means person number one in the set), followed by the time in minutes taken to pass a message to that person. There are no special punctuation symbols or spacing rules.

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

For each set of data, your program must output a single line containing the person who results in the fastest message transmission, and how long before the last person will receive any given message after you give it to this person, measured in integer minutes.
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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章