1. 這是求最小環的模板題
2. 這是輸出路徑的模板題
由於都是模板題,題意就不再贅述,直接從演算法講起~
floyd演算法是通過類似動態規劃的方法求解最短路徑問題的高效演算法,對於正權值和負權值(不含負環)都有效.該演算法主要分為兩步:第一步初始化,對於從u到v的邊,用鄰接矩陣mp[u][v]儲存路徑的權值,若無這條邊則為無窮大(實際寫時定成比較大的數即可),第二步狀態轉移,對於每一對點u,v,列舉是否有點w使得u->w->v的最短路徑比u->v的最短路徑小,如果是則更新它.
核心的狀態轉移**如下:
mp[i][j] = min( mp[i][j], mp[i][k]+mp[k][j] );
floyd法已求得了到最外層迴圈k時,所有點對間以點1,2,……,k-1為中間點的最短路徑.對於每乙個環,這個環可以看為最大編號的點c與其相鄰的兩個點 a 和b 與 a 到 b 的最短路上的點.因此可以用floyd法拓展.
下面是完整**:
#include
using
namespace
std;
typedef
long
long
int ll;
const ll inf=1e9;
const ll maxn=110;
ll mp[maxn][maxn],dis[maxn][maxn];
ll n,m,u,v,len,mincost,temp,num,s;
void init()
}for(int i=1; i<=m; i++)
}void floyd() }}
}}int main()
我們用乙個road陣列儲存輸出的最小路徑,在每次更新最小環的值時更新這一陣列,從開始的點s不斷向前推即可.
cnt=0;
s=j;
while(s!=i)
road[cnt++]=i;
road[cnt++]=k;
這就是最小環路徑的記錄部分,注意p陣列的初始化,將p[i][j]初始化為i,p[i][j]表示從i到j的路徑中經過的第乙個點.
下面是完整**:
#include
#include
using
namespace
std;
typedef
long
long
int ll;
const
int inf=1e6;
const
int maxn=110;
int mp[maxn][maxn],dis[maxn][maxn],road[maxn],p[maxn][maxn];
int n,m,u,v,len,mincost,temp,cnt,s;
void init()
}for(int i=1; i<=m; i++)
}void floyd()
road[cnt++]=i;
road[cnt++]=k;}}
}for(int i=1; i<=n; i++) }}
}}int main()
}return
0;}
演算法學習 1
插入排序是學習演算法時最先學到的乙個演算法,很簡單,也許看一遍就會理解,從而覺得自己掌握這個基本的演算法。但是很多人可能會像我一樣,過了一段時間,提筆來寫一下插入排序的偽 就很難寫出書本上如此優雅的偽 insertion sort a for j 2 to a.length key a j inse...
演算法學習 1
劍指offer演算法題 題目描述 給你一根長度為n的繩子,請把繩子剪成整數長的m段 m n都是整數,n 1並且m 1,m n 每段繩子的長度記為k 1 k m 請問k 1 x xk m 可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此時得到的最大乘積是18。...
演算法學習1
求最大子列和問題 給定n個整數的序列,求最大連續子列和,演算法 求出每乙個子列的和 然後得到最大的和返回 static intmaxsum1 int arr if maxsumreturn maxsum 時間複雜度 t n 3 空間複雜度 o 1 優化1 已經計算過的子列和不需要重複計算,再已經計算...