【6.12校內test】T3 城市交通費

要不我先去寫T2吧(逃ios

先把題目搞上來:數組

【問題描述】 有 n 個城市,編號 1~n。其中 i 號城市的繁華度爲 pi。省內有 m 條能夠雙向同行的高速 公路,編號 1~m。編號爲 j 的高速公路鏈接編號爲 aj 和 bj 兩個城市,通過高速公路的費用 是 wj。若從城市 x 出發到某城市 y,除了須要繳納高速公路費用,還要繳納「城市建設費」 (爲從 x 城市到 y 城市所通過的全部城市中繁華度的最大值,包括 x 和 y 在內)。spa

現提出 q 個詢問,每一個詢問給出一組 x 和 y,你須要回答從 x 出發到 y 城市,所須要的 最低交通費(高速公路費+城市建設費)是多少。3d

【輸入】code

第一行三個整數 n,m,q。 第二行 n 個整數,表示 p1~pn。blog

接下來 m 行中,每行 3 個正整數,第 j 行包含 Aj,Bj,Wj。排序

隨後 Q 行每組兩個正整數 x,y 表示一組詢問。string

【輸出】it

共 Q 行,爲對 Q 個問題的回答:x 城市到 y 城市的最小交通費用。io

【樣例輸入】

5 7 2

2 5 3 3 4

1 2 3

1 3 2

2 5 3

5 3 1

5 4 1

2 4 3

3 4 4

1 4

2 3

【樣例輸出】

8 9

【數據範圍及約定】

n≤250,m≤20000,Q≤10000,Pi≤10000,Wj≤2000,保證任意兩個城市能夠互相到達。

【樣例說明】 圖中,表明城市的格子中第一個數字是城市編號,第二個紅色數字是該城市的繁華度。

(1)從城市 1 到城市 4 的最小交通費用路線是:1 3 5 4;公路費是 2+1+1=4;城市建設費是 max{2,3,4,3}=4;總交通費用 4+4=8。

(2)從城市 2 到城市 3 的最小交通費用路線是:2 5 3;公路費是 3+1=4;城市建設費是 max{5,4,3}=5;總交通費用 4+5=9。


(跑回來補鍋:

SOLUTION:

  1. 首先固然是存圖啦,這裏用鄰接矩陣存圖就行了。可是你覺得這麼容易的嗎,你永遠想一想不到毒瘤出題人是怎麼想的,這套題的數據點竟然兩個城市之間有超過一條的路徑???慌得一批,這數據也是毒瘤的沒誰了;
  2. 接下來是一些跑floyd的初始化:由於要加繁華度,所以咱們要開兩個二維數組來分別記錄只最短路和加了繁華度的最短路;對於只記錄最短路的二維數組a[i][j],用memset初始化爲一個很大的數,在樓上存圖時記得更新某兩點間有一條路徑(順序寫反了可是不想改),接下來順帶講一下memset的賦值是怎麼賦的:
    • memset按位賦值:一位等於8字節(一個int型是4位),(一字節能夠看作是二進制中的一位),對於memset,不管你這個數是什麼,它都會把每一位都變成第一位的數,若是咱們用memset賦值1的話,最後結果就是這個數:

(一個藍框爲1位)

而本題中memset(a,63,sizeof(a));就是把a數組的初始值賦成了如下這個數:

好了繼續講初始化:初始化a[i][i]=0(本身到本身顯然是0),用一個數組t[i]來記錄下標,講t數組按繁華度從小到大排序(講真的這個排序我是第一次見/果然仍是我太蒟了嗎qwq)

這樣咱們來看一看樣例排序後:也就是如今t[1]---t[n]分別對應着繁華度最低的城市的編號到繁華度最高的城市的編號;

預處理f[i][j]=a[i][j]+max(p[i],p[j]);這樣若是兩城市之間原本就有路聯通的話,那麼能夠先被更新掉,若是不連通,能夠近似的看爲INF;

3.最核心的floyd部分,也是你們討論了很久的部分:

    1. floyd其實是一個DP(floyd:哈哈想不到吧qwq)
    2. floyd實際上是一個三維DP
    3. floyd其實就跟01揹包同樣把k這一維降掉了,所以k要放在最外層枚舉;
    4. 對於沒有降維的三維floyd disk,i,j來說,表示的是從i=>j只可能通過1——k這些點的最短路徑;
    5. 對於這個題來說:f[k][i][j]表示的就是從i=>j只可能通過1——k這前k個繁華福低的城市,由於這裏枚舉的k其實枚舉的是第k的最不繁華城市,因此此時k城市必定是1——k中繁華度最高的,所以對於f[i][j]來講,此時要加的繁華度就是i城市,j城市和k城市中最大的一個;

4.最後就是輸入詢問而後直接輸出f[x][y]就好啦

(撒花✿✿ヽ(°▽°)ノ✿)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
int n,m,q,p[300],aj,bj,wj,x,y,f[300][300],a[300][300],top,t[300];
int cmp(int x,int y)
{
    return p[x]<p[y];
}
int main()
{
    memset(a,63,sizeof(a));
    top=0;
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&aj,&bj,&wj);
        a[aj][bj]=min(a[aj][bj],wj);
        a[bj][aj]=min(a[bj][aj],wj);//聽說是防止出現aj到bj有兩條路的狀況呀 
        //記錄從aj到bj有一條路徑,從bj到aj有一條路徑(由於 雙向通行) 
    }
    for(int i=1;i<=n;i++)
    {
        a[i][i]=0;//本身到本身顯然有一條爲0的最短路 
        t[i]=i;//這裏好像是防止排序後找不到哪一個是哪一個下標吧?? 
    }
    sort(t+1,t+1+n,cmp); 
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            f[i][j]=a[i][j]+max(p[i],p[j]);//先初始化最短路爲這兩點間的距離+這兩點中p較大的p值 
    for(int k=1;k<=n;k++)//floyd
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                a[i][j]=min(a[i][j],a[i][t[k]]+a[t[k]][j]);//幹求最短路 
                f[i][j]=min(f[i][j],a[i][j]+max(p[i],max(p[j],p[t[k]])));
            }
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",f[x][y]);
    }
    return 0;
}

nice end-

相關文章
相關標籤/搜索