2017-10-7 vijos 無向圖最短路徑
描述
無向圖最短路徑問題,是圖論中最經典也是最基礎的問題之一。本題我們考慮一個有 nn 個結點的無向圖 GG。
GG 是簡單完全圖,也就是說 GG 中沒有自環,也沒有重邊,但任意兩個不同的結點之間都有一條帶權的雙向邊。
每一條邊的邊權是非負實數,但我們並不知道每一條邊的具體邊權。
好訊息是我們知道 GG 中任意兩點最短路徑的長度d(i,j)d(i,j)。且保證至少有一種邊權的分配方案滿足得到的帶權圖中ii與jj的最短路長度恰好是d(i,j)d(i,j)。
下面是留給你的任務:對於任意一對點(i,j)(i,j),希望你能找出來所有合法的邊權分配方案中ii和jj之間邊權的最大值。
格式
輸入格式
本題中,每一組資料都有多次詢問,每一次詢問分別給出了一個無向圖GG。
輸入的第一行是一個整數 tt,表示總共的詢問個數。之後依次給出每一次詢問。
對於每一次詢問來說,第一行給出了 G 中結點總數 n。之後n行每行有n個整數,給出了一個n×n的矩陣 d,其中第ii行第jj列的整數對應 d(i,j)d(i,j)表示ii到jj的最短路徑長度。
因為圖GG是簡單無向圖,對角線元素d(i,i)d(i,i)總是0,且矩形是對稱的(也就是說d(i,j)=d(j,i)d(i,j)=d(j,i))。
輸出格式
對於每一次詢問,若給定的圖GG有nn個結點,則輸出nn行,每行有nn個整數,描述了一個矩陣 aa。矩陣的第ii行第jj列表示連線ii和jj的邊的最大可能邊權。如果(i,j)(i,j)的邊權可以任意大,則輸出字串infty表示無限。
矩陣的對角線沒有實質性意義,請全輸出00。因為GG是無向圖,所以輸出的矩陣aa應該也是對稱的(即a(i,j)=a(j,i)a(i,j)=a(j,i))。
不難發現,因為給定的矩陣 dd 中每一個數字都是整數,所以最大可能邊權總會是整數。
樣例1
樣例輸入1
2
3
0 2 8
2 0 10
8 10 0
3
0 1 1
1 0 1
1 1 0
樣例輸出1
0 2 8
2 0 infty
8 infty 0
0 1 1
1 0 1
1 1 0
限制
對於 20\%20% 的資料,有 n = 3n=3。
對於 50\%50% 的資料,有 1≤n≤10。
對於 100\%100% 的資料,有 1≤n≤100,且所有詢問中nn的和不超過 800800,對於所有的dd滿足1≤d≤256。
每一組資料的時限為 0.5 秒。
題解
這個題挺有意思。
題目大意:給出的是所有兩點間的最短路徑,要求出圖中兩點的可能的最大邊權,不會對最短路產生影響。
怎麼考慮這個問題呢?首先我們把給出的最短路暫定為兩條邊之間的邊權,然後跑floyed,要求是不能只經過一條路到達(即把兩點間的最短路抹掉),如果這樣得出的兩點間的最短路於原來的最短路相等,那麼直接連線這兩個點的邊可以任意大,否則就不變。
怎麼能讓他不能一條邊到達呢?重新開一個數組記錄。
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,n,d[101][101],m[101][101];
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
scanf("%d",&d[i][j]);
// for (int i=1; i<=n; i++) m[i][i]=0x7fffffff;
memset(m,0x7f,sizeof(m));
for (int k=1; k<=n; k++)
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
if (i!=j&&j!=k&&i!=k)
m[i][j]=min(m[i][j],d[i][k]+d[k][j]);
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
{
if (m[i][j]==d[i][j]&&i!=j) d[i][j]=-1;
}
for (int i=1; i<=n; i++)
{
for (int j=1; j<=n; j++)
if (d[i][j]==-1) printf("infty ");//==和=
else printf("%d ",d[i][j]);
printf("\n");
}
}
return 0;
}
對noip來說,可能不需要那麼多的演算法。需要做到的是如何獨立的思考問題,並將自己的想法轉化成程式碼。同時還要做到認真,細緻。