基礎最短路模板:
有 n 個人,他們的編號為 1~n,其中有一些人相互認識,現在 x 想要認識 y,可以通過他所認識的人來認識更多的人
(如果 x 認識 y、y 認識 z,那么 x 可以通過 y 來認識 z),求出 x 最少需要通過多少人才能認識 y。
【輸入格式】
第 1 行 3 個整數 n、x、y,n≤100,1≤x、y≤n。
接下來是一個 n×n 的鄰接矩陣,a[i][j]=1 表示 i 認識 j,a[i][j]=0 表示不認識。
保證 i=j 時,a[i][j]=0,並且 a[i][j]=a[j][i]。
【輸出格式】
輸出一行一個數,表示 x 認識 y 最少需要通過的人數。
【樣例輸入】
5 1 5
0 1 0 0 0
1 0 1 1 0
0 1 0 1 0
0 1 1 0 1
0 0 0 1 0
【樣例輸出】
2
#include<bits/stdc++.h>
using namespace std;
/*
1.可以直接跑BFS
2.無向圖最短路徑,因為只有輸入只有一次查詢,那么dijkstra,spfa都可以
dijkstart:因為權值全都為1,所以就不用考慮堆優化.
3.還有一種多源不含負權最短路徑,floyd 算法,時間復雜度0(n^3),填空題可以使用一下
借用的是動態規划的思路
*/
int u[105][105];
int n,X,Y;
int bfs(){
queue<pair<int,int>>que;//先進先出,對於每一個條路線需要記錄所走的路徑長度
vector<int>judg(n+1,0);//標記數組
que.push({X,0});
while(!que.empty()){
pair<int,int> k=que.front();
que.pop();
if(k.first==Y){
return k.second-1;//訪問到時走的路程-1就是訪問的人數
}
if(judg[k.first])continue;//標記點,防止反復訪問同一個點
judg[k.first]=1;
for(int i=1;i<=n;i++){
if(i!=k.first&&u[k.first][i]==1){
if(!judg[i]){
que.push({i,k.second+1});
}
}
}
}
return 0;
}
//單源最短路徑,不含負權
int dijkstra(int x){
/*
在權值不同的時候,每次取隊首的元素,優化到保證是里面最小的,需要把隊列改成優先隊列
*/
vector<int>ans(n+1,INT_MAX/2);//ans[i]記錄x到i的距離
vector<int>judg(n+1,0);//標記數組,保證點只被訪問一次
queue<int>que;
que.push(x);
ans[x]=0;
while(!que.empty()){
int k=que.front();
que.pop();
if(judg[k])continue;//被標記過
judg[k]=1;
for(int i=1;i<=n;i++){
//if 保證不是自己到自己 k->i存在邊
if(k!=i&&u[k][i]==1&&ans[i]>ans[k]+1){//更新距離,如果x->i的距離大於x->k->i,就跟新
ans[i]=ans[k]+1;
if(!judg[i]){ //滿足沒有被訪問過,加入隊列
que.push(i);
}
}
}
}
return ans[Y]-1;//
}
//包含負權,特判是否存在負環
int spfa(int x){
vector<int>ans(n+1,INT_MAX/2);//ans[i]記錄x到i的距離,類似於dijkstra
vector<int>judg(n+1,0);//標記數組,保證隊列內不存在重復的點
vector<int>e(n+1,0); //特判數組,表示每個點入棧多少次,如果超過總點數就說明存在負環,一直循環
queue<int>que;
que.push(x);//進隊
ans[x]=0;
e[x]++;
while(!que.empty()){
int k=que.front();
que.pop();
if(e[k]>n)return false;//存在負環,找不到答案
judg[k]=false;//不存隊列中了
for(int i=1;i<=n;i++){
if(k!=i&&u[k][i]==1&&ans[i]>ans[k]+1){
ans[i]=ans[k]+1;
if(!judg[i]){ //不存在隊列,加入
judg[i]=true;
e[i]++;
que.push(i);
}
}
}
}
return ans[Y]-1;
}
//多源最短路徑
int floyd(int x,int y){
vector<vector<int>>ans(n+1,vector<int>(n+1,INT_MAX/2));//ans[i][j]表示i->j的距離
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(u[i][j]){
ans[i][j]=1;//所有的距離都是1
}
}
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(ans[i][j]>ans[i][k]+ans[k][j]){
ans[i][j]=ans[i][k]+ans[k][j];
}
}
}
}
return ans[x][y]-1;
}
int main(){
scanf("%d%d%d",&n,&X,&Y);
//編號從1開始,那么所有的都按1
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&u[i][j]);
}
}
// printf("%d",bfs());
// printf("%d",dijkstra(X));//求x->到所有的距離
// printf("%d",spfa(X)); //求x->到所有的距離
printf("%d",floyd(X,Y)); //x->y的距離
return 0;
}