1. 程式人生 > >P1744 采購特價商品 題解(講解圖論)

P1744 采購特價商品 題解(講解圖論)

最短 inf info target ping 分享 組成 printf 。。

圖論的超級初級題目(模板題)

最短路徑的模板題

圖是啥?(白紙上的符號?)

對於一個擁有n個頂點的無向連通圖,它的邊數一定多於n-1條。若從中選擇n-1條邊,使得無向圖仍然連通,則由n個頂點及這 n-1條邊(弧)組成的圖被稱為原無向圖的生成樹。

換句話說,有邊有點就是圖。(本蒟蒻的理解是這樣。。QWQ)

另外,還有一些與圖有關的定義(很好理解,通俗一點):

階:圖中點的個數。

邊:兩個點間的連接

權值:邊的長度

。。。想了解更多找度娘,她可能講的比我通俗QWQ。

鄰接矩陣:

技術分享圖片

進入正題:

題目背景

《愛與愁的故事第三彈·shopping》第一章。

題目描述

中山路店山店海,成了購物狂愛與愁大神的“不歸之路”。中山路上有n(n<=100)家店,每家店的坐標均在-10000~10000之間。其中的m家店之間有通路。若有通路,則表示可以從一家店走到另一家店,通路的距離為兩點間的直線距離。現在愛與愁大神要找出從一家店到另一家店之間的最短距離。你能幫愛與愁大神算出嗎?

輸入輸出格式

輸入格式:

共n+m+3行:

第1行:整數n

第2行~第n+1行:每行兩個整數x和y,描述了一家店的坐標

第n+2行:整數m

第n+3行~第n+m+2行:每行描述一條通路,由兩個整數i和j組成,表示第i家店和第j家店之間有通路。

第n+m+3行:兩個整數s和t,分別表示原點和目標店

輸出格式:

僅一行:一個實數(保留兩位小數),表示從s到t的最短路徑長度。

輸入輸出樣例

輸入樣例#1: 復制
5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5
輸出樣例#1: 復制
3.41

說明

100%數據:n<=100,m<=1000

先預處理轉化為鄰接矩陣後再直接輸出就可以了

具體算法為Floyd算法

上AC代碼:

#include<cstdio>
#include<cstring>
#include<cmath>
#include
<iostream> using namespace std; int n,m,a[101][2],e,g,aa,bb;//a用來存x,y坐標 double f[101][101];//f用來存路徑的 int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) cin>>a[i][0]>>a[i][1]; //scanf("%d%d",&a[i][0],&a[i][1]); scanf("%d",&m); memset(f,0x7f,sizeof(f)); for(int i=1;i<=m;i++) { scanf("%d%d",&e,&g);//代替x,y ,因為cmath中有x,y了(真的很無語啊) f[g][e]=sqrt(pow(double(a[e][0]-a[g][0]),2)+pow(double(a[e][1]-a[g][1]),2)); f[e][g]=sqrt(pow(double(a[e][0]-a[g][0]),2)+pow(double(a[e][1]-a[g][1]),2)); } scanf("%d%d",&aa,&bb); for(int k=1;k<=n;k++)//開啟O(n^3)暴力模式—— for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if((i!=j)&&(i!=k)&&(j!=k)&&(f[i][j]>(f[i][k]+f[k][j]))) f[i][j]=f[i][k]+f[k][j]; } printf("%0.2lf",f[aa][bb]);//暴力過後松一口氣,直接輸出您想要的點就行了 return 0; }

完結?ヽ(°▽°)ノ?

希望對大家有所幫助

P1744 采購特價商品 題解(講解圖論)