1. 程式人生 > >第16次CCF CSP認證-第5題-317 號子任務(subtask317)-圖論最短路徑

第16次CCF CSP認證-第5題-317 號子任務(subtask317)-圖論最短路徑

amp 查看 最短 ima efi class task 分享圖片 標準輸入

【題目背景】
“你在平原上走著走著,突然迎面遇到一堵墻,這墻向上無限高,向下無限深,向
左無限遠,向右無限遠,這墻是什麽?”——《流浪地球》原著
我們帶著地球去流浪了,為了處理流浪過程中可能會發生的危機,聯合政府找到
你,希望你能協助完成 317 號子任務:制定應急預案。
【題目描述】
地球的表面有 n 個據點,這些據點之間存在 m 條雙向道路。
這些據點中,有的是建立在行星發動機之下,受到行星發動機的保護(行星發動機
據點),而其他據點則沒有行星發動機的保護(普通據點,比如燃料采集據點/科研據點
等)。
當發生危機的時候,沒有行星發動機的保護是非常危險的,所以每個人都需要趕到

最近的行星發動機據點尋求庇護,然而行星發動機據點也不一定安全,再加上行星發動
機據點容量有限,所以有些時候得去第二近或者第三近的行星發動機據點。
聯合政府找到你,希望你能夠計算出每個據點最近的 k 個行星發動機據點,為了
簡化問題,你只需要輸出每個據點到最近 k 個行星發動機據點的最短距離之和,如果
某個據點能夠到達的行星發動機據點不足 k 個,則輸出其能到達的所有行星發動機的
最短距離之和。
【輸入格式】
從標準輸入讀入數據。
輸入的第一行包含三個用空格隔開的整數 n, m, k ,含義見題目?述,保證 1 ≤ n ≤
104, 0 ≤ m ≤ 104, 1 ≤ k ≤ 102。據點依次編號為 1 到 n 。
第二行包含 n 個整數依次表示每個據點的類型,每個數為 1 或 0 (1 表示對應據
點為行星發動機據點,0 表示普通據點)。
接下來 m 行,每行三個整數 u, v,w 表示有一條長度為 w 的雙向道路連接 u 號據點
和 v 號據點,1 ≤ u, v ≤ n, 1 ≤ w ≤ 103 。
可能有重邊和自環。
【輸出格式】
輸出到標準輸出。
輸出 n 行,每行輸出一個整數表示答案(見題目?述)

【樣例 1 輸入】
7 6 2
1 0 1 0 1 1 0
1 4 1
1 2 3
2 4 4
2 3 5
2 5 7
6 7 5
【樣例 1 輸出】

8

8

10

10

0

5

【樣例 1 解釋】
該樣例的輸入對應的圖如下,其中紅色點是行星發動機據點,白色點是普通據點。

技術分享圖片

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 const int amn=1e4+5;
 8 const int inf=9e7;
 9 ll ans[amn];
10 int typ[amn],e[amn][amn],k,n,m;
11 int main()
12 {
13     cin>>n>>m>>k;
14     for(int i=1; i<=n; i++)
15     {
16         for(int j=1; j<=n; j++)
17         {
18             if(i==j)e[i][j]=0;
19             else e[i][j]=inf;
20         }
21     }
22     for(int i=1; i<=n; i++)
23     {
24         int tt;
25         cin>>tt;
26         typ[i]=tt;
27     }
28     int u,v,w;
29     for(int i=1; i<=m; i++)
30     {
31         cin>>u>>v>>w;
32         e[u][v]=w;
33         e[v][u]=w;
34     }
35     for(int c=1; c<=n; c++)
36     {
37         for(int i=1; i<=n; i++)
38         {
39             for(int j=1; j<=n; j++)
40                 if(e[i][k]<inf&&e[k][j]<inf&&e[i][j]>e[i][c]+e[c][j])
41                     e[i][j]=e[i][c]+e[c][j];
42         }
43     }
44 //    cout<<endl<<endl;///查看圖的最短路徑(調試用)
45 //    for(int i=1; i<=n; i++)
46 //    {
47 //        for(int j=1; j<=n; j++)
48 //        {
49 //            printf("%10d",e[i][j]);
50 //        }
51 //        cout<<endl<<endl;
52 //    }
53     for(int i=1; i<=n; i++)
54     {
55         int top=0;
56         memset(ans,0,sizeof(ans));
57         for(int j=1; j<=n; j++)
58         {
59             if(e[i][j]<inf&&typ[j])
60             {
61                 ans[top++]=e[i][j];
62             }
63         }
64         sort(ans,ans+top);
65         ll sum=0;
66         for(int i=0; i<k&&i<top; i++)
67         {
68             sum+=ans[i];
69         }
70         cout<<sum<<endl;
71     }
72     return 0;
73 }
74 /*
75 樣例
76 
77 7 6 2
78 1 0 1 0 1 1 0
79 1 4 1
80 1 2 3
81 2 4 4
82 2 3 5
83 2 5 7
84 6 7 5
85 
86 */

第16次CCF CSP認證-第5題-317 號子任務(subtask317)-圖論最短路徑