安徽省2016“京勝杯”程序設計大賽_H_單身晚會

單身晚會

Time Limit: 1000 MS Memory Limit: 65536 KB
Total Submissions: 53 Accepted: 16

Description


​ZJ和ZCX在一起很久了,兩個人都互生愛意,最終決定喜結良緣,從此踏入浪漫的婚姻殿堂。

但是,ZJ的好基友們想到以後ZJ就不能經常跟他們一起愉快的玩耍了,都覺得非常傷心難過,於是他們決定在最後一晚爲ZJ開一場單身晚會,玩整晚緊張刺激的飛行棋。

ZJ的好基友居住在城市的各個地方(每個地方不一定只有一個基友),他們需要從各個地方趕到其中一個朋友的家裏來參加這最後的單身PARTY,ZJ被基友們的熱情深深感動了,決定對基友們來時的路費進行報銷。報銷規則按照距離來計算。基友們爲了幫ZJ省錢,決定在所有人走最短路徑的情況下,總距離最小的人的家裏開PARTY。

ZJ想知道基友們走過的總距離是多少,然後他把總共需要報銷的錢拿出來,就可以讓基友們自己來分配了。但是他算了半天也沒算出來總距離是多少,單身PARTY馬上就開始了,你能幫幫他嗎?



Input


         第一行一個整數T,表示有T(T<15)組數據

每組數據的第一行基友數(包括ZJ)N(N<100),路口P(2<=P<=100),路口之間道路數C(1<=C<=1450),(基友的編號爲1…N,路口的編號爲1…P)

第二行到第N+1行:編號爲1到N的基友們家所在的路口號。

第N+2行到N+C+1行:每行有三個數:相連的路口A,B,路口間間距D(1<=D<=255),當然,連接是雙向的。


Output


每組數據輸出佔一行,輸出大家必須要走的最小距離和


Sample Input


1
3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5

Sample Output


8

Hint


經測試,本題數據和題意不符合,現對題意做如下修正:
選擇一個路口(不一定要有人住),使所有人到這個路口的路程和最小化
這題應該是省賽現場修改題意,但這裏用的是原題意,特此說明。對被卡的同學再次表示歉意。對其他題目有疑義的可以發信件給賬號instankill詢問。

這道題在省賽中改過題意,重新A時發現自己很多次也提交不過,感覺Hint的注意也寫的不是很清晰。
題解:這道題是典型的利用Floyd算法求最短路徑的問題,有關Floyd算法此處省略,網上有很多,介紹的也很詳細。先利用Floyd算法求出任意兩個路口的最短路徑。最後求任意一個路口到所有基友的距離之和,最後找到最小值,也就是在路口也是可以開party的。一開始也是沒明白題意,理解成要在基友家裏開party,所以老是Wrong Answer。只要注意這點應該就沒有問題了

#include <iostream>
#include <cstdio>
#include <cstring>
typedef long long LL;
const LL INF = 1000000000;

using namespace std;

int a[101];
LL L[101][101];
int n, p, c;

void floyd() //Floyd最短路徑算法
{
    for (int k=1; k<=p; k++)
        for (int i=1; i<=p; i++)
            for (int j=1; j<=p; j++)
                L[i][j] = min(L[i][j], L[i][k]+L[k][j]);
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d%d", &n, &p, &c);
        for (int i=1; i<=n; i++)
            scanf("%d", &a[i]);
        int A, B, D;
        for (int i=1; i<=p; i++)
            for (int j=1; j<=p; j++)
                L[i][j] = INF;
        for (int i=1; i<=p; i++)
            L[i][i] = 0;
        for (int i=0; i<c; i++) {
            scanf("%d%d%d", &A, &B, &D);
            L[A][B] = D;
            L[B][A] = D;
        }
        floyd();
        LL Smin = INF, s = 0;
        for (int i=1; i<=p; i++) {
            s = 0;
            for (int j=1; j<=n; j++) {
                if (L[i][a[j]] >= INF) //先排除無窮大的邊
                    goto to; //出現就進入下一次循環
                s += L[i][a[j]];
            }
            Smin = min(Smin, s); //求出每次的最短路徑
            to:;
        }
        printf("%d\n", Smin);
    }
    return 0;
}



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