vijos 观光旅游 最小环fl 呆详看
背景
湖南師大附中成為百年名校之后,每年要接待大批的游客前來參觀。學校認為大力發(fā)展旅游業(yè),可以帶來一筆可觀的收入。
描述
學校里面有N個景點。兩個景點之間可能直接有道路相連,用Dist[I,J]表示它的長度;否則它們之間沒有直接的道路相連。這里所說的道路是沒有規(guī)定方向的,也就是說,如果從I到J有直接的道路,那么從J到I也有,并且長度與之相等。學校規(guī)定:每個游客的旅游線路只能是一個回路(好霸道的規(guī)定)。也就是說,游客可以任取一個景點出發(fā),依次經過若干個景點,最終回到起點。一天,Xiaomengxian決定到湖南師大附中旅游。由于他實在已經很累了,于是他決定盡量少走一些路。于是他想請你——一個優(yōu)秀的程序員——幫他求出最優(yōu)的路線。怎么樣,不是很難吧?(摘自《郁悶的出納員》)
格式
輸入格式
對于每組數(shù)據(jù):
第一行有兩個正整數(shù)N,M,分別表示學校的景點個數(shù)和有多少對景點之間直接有邊相連。(N<=100,M<=10000)
以下M行,每行三個正整數(shù),分別表示一條道路的兩端的編號,以及這條道路的長度。
輸出格式
對于每組數(shù)據(jù),輸出一行:
如果該回路存在,則輸出一個正整數(shù),表示該回路的總長度;否則輸出“No solution.”(不要輸出引號)
樣例1
樣例輸入1
5 7 1 4 1 1 3 300 3 1 10 1 2 16 2 3 100 2 5 15 5 3 20 4 3 1 2 10 1 3 20 1 4 30樣例輸出1
61 No solution.限制
各個測試點1s
?
by? http://wenku.baidu.com/view/c6382a41a8956bec0975e3c0.html?from=related
????? http://blog.csdn.net/youngyangyang04/article/details/7054931
典型的最小環(huán)問題
因為n很小可以直接Floyd求最小環(huán)
注意最小環(huán)ans更新的位置
每次枚舉k為下家更新點
應該先嘗試更新ans再更新i,j之間的最短路
我們用g[i][j]來記錄i,j之間最短路徑
而w[i][j]用來保存i,j之間的原始路徑長度
因為我們知道i,j要構成一個最小環(huán)
肯定要有兩條路可走
1.直接從i到j。
2.從i經過某個中途點k到達j
即對于每一個k 我們先嘗試從這個k點對于所有的i,j點能不能得到最小環(huán)
然后我們再用這個k點嘗試更新路徑
該算法的證明:
一個環(huán)中的最大結點為K(編號最大),與其相連的兩個點為i,j ,
這個環(huán)的最短長度為: g[i][k] + g[k][j] + i到j的路徑中所有結點編號都不大于k的最短路徑長度,
根據(jù)floyd的原理,在最外層循環(huán)做一個k-1次之后,
g[i][j] 則代表了i到j的路徑中所有結點的編號都不大于k的最短路徑。
所以我們枚舉的i,j要有
1<=i<k,i<j<k
再換一種說法吧
比普通Floyd多出來的部分,主要利用到的原理是當處理到k時,
所有以1 到k - 1為中間結點的最短路徑都已經確定,
則這時候的環(huán)為(i到j(1 < i, j <= k - 1)的最短路徑) + 邊(i, k) + 邊(k, j)
遍歷所有的i, j找到上述式子的最小值即位k下的最小代價環(huán) ?
*/
/*
路徑的求法:
用一個pre[i][j]記錄j前面的一個頂點, 初始化為i,當出現(xiàn)需要更新的時候則將pre[i][j] = pre[k][j];
若i== j的時候則表示找全了路徑,最后將k點加入路徑中
核心代碼:
While(i != j)
{ ?
??? if (i != j)
??? { ?
??????? Path[len++] = j;
??????? J = pre[i][j];
??? } ?
???? Path[len++] = i;
}
?
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std;const int INF=1e8; int w[102][102],g[102][102]; int n,e;void init() {int x,y,v;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)w[i][j]=g[i][j]=INF;for(int i=1;i<=e;i++){scanf("%d%d%d",&x,&y,&v);w[x][y]=w[y][x]=g[x][y]=g[y][x]=v;} }void work() {int ans=INF;for(int k=1;k<=n;k++){for(int i=1;i<k;i++)//最小環(huán)for(int j=i+1;j<k;j++)//為了避免一條邊計算兩次并且i == j時因為權重會出錯 ans=min(ans,g[i][j]+w[i][k]+w[k][j]);for(int i=1;i<=n;i++)//Floydfor(int j=1;j<=n;j++)if(i!=j)g[i][j]=min(g[i][j],g[i][k]+g[k][j]);}if(ans==INF)printf("No solution.\n");elseprintf("%d\n",ans); }int main() {while(scanf("%d%d",&n,&e)!=EOF){init();work();} }?
轉載于:https://www.cnblogs.com/lyqlyq/p/7123286.html
總結
以上是生活随笔為你收集整理的vijos 观光旅游 最小环fl 呆详看的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java Enumset
- 下一篇: 字符串转Unicode码