EOJ_1094_寻找航海路线
生活随笔
收集整理的這篇文章主要介紹了
EOJ_1094_寻找航海路线
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3fusing namespace std;/*Prim算法需要的全局變量*/
bool visited [501];
int cost[501][501];
int pre[501];
int lowc[501];
/*Prim算法需要的全局變量*/
/*次小生成樹需要的全局變量*/
bool used[501][501]; //標(biāo)記邊是否被用在最小生成樹中
int max_edge[501][501]; //記錄兩個(gè)點(diǎn)之間最長(zhǎng)的邊的長(zhǎng)度
/*次小生成樹需要的全局變量*/int Prim(int n)
{int total = 0, index;for(int i=2; i<=n; ++i){lowc[i] = cost[1][i];if(lowc[i]<INF)pre[i] = 1;}pre[1] = 0;visited[1] = true;for(int i=2; i<=n; ++i){int min_e = INF;for(int j=2; j<=n; ++j){if(!visited[j] && lowc[j]<min_e){min_e = lowc[j];index = j;}}total += lowc[index];visited[index] = true;used[index][pre[index]] = used[pre[index]][index] = true; //標(biāo)記這條邊用過了for(int j=2; j<=n; ++j){if(!visited[j] && cost[index][j]<lowc[j]){lowc[j] = cost[index][j];pre[j] = index;}if(visited[j] && j!=index) //更新最長(zhǎng)邊//這里其實(shí)是動(dòng)態(tài)規(guī)劃,假設(shè)2-3-4-5聯(lián)通,求2-5中的最長(zhǎng)邊,//其實(shí)就是等價(jià)于2-3-4中的最長(zhǎng)邊與4-5邊中的較大值//即max(max_edge(2-3-4),length(4-5))max_edge[index][j] = max_edge[j][index] = max(max_edge[pre[index]][j], lowc[index]);}}return total;
}int second_st(int n, int MST)
{int total = INF;/*遍歷所有邊*/for(int i=1; i<=n; ++i)for(int j=i+1; j<=n; ++j){if(!used[i][j] && cost[i][j]<INF)total = min(MST-max_edge[i][j]+cost[i][j], total);}if(total == INF) //找不到次小生成樹total = -1;return total;
}int main()
{int N, M, u, v, w, MST, SMT;while(cin>>N>>M){memset(visited, 0, sizeof(visited));memset(max_edge, 0, sizeof(max_edge));memset(used, 0, sizeof(used));for(int i=1; i<=N; ++i)for(int j=1; j<=N; ++j)cost[i][j] = INF;for(int i=0; i<M; ++i){cin>>u>>v>>w;cost[u][v] = w;cost[v][u] = w;}MST = Prim(N);SMT = second_st(N, MST);cout<<MST<<' '<<SMT<<endl;}return 0;
}
用定義,得到所有的生成樹(spanning tree),路徑總和排第二的就是次小生成樹 求得最小生成樹后枚舉n-1條邊,循環(huán)n-1次,分別去掉第i(i ∈\in∈ [1,n-1])條邊后得到的最小生成樹路徑,用vector存儲(chǔ),取最小值即可 根據(jù)“次小生成樹一定在最小生成樹的臨集中”定理 枚舉要加入哪條新邊(U-V),加入后會(huì)出現(xiàn)一條回路,因此刪除的邊必須是在MST上從u到v的路徑上,而且是這條路徑的最長(zhǎng)邊 因?yàn)榇涡∩蓸涞穆窂胶团c最小生成樹的路徑和之差等于加入的邊與刪除的邊之差, 即求MST外的一條邊與邊的端點(diǎn)間最長(zhǎng)邊長(zhǎng)度之差 再遍歷所有MST外的邊即可
prim 算法模板是用 lowc[i] = 0 表示點(diǎn)i 被選中 在動(dòng)態(tài)規(guī)劃得到max_edge時(shí)注意lowc[j]此時(shí)為0 即使在動(dòng)態(tài)規(guī)劃中解決了lowc[j]==0的問題(用一個(gè)tmpLostc暫時(shí)存儲(chǔ)lowc[j]即可),我也沒有成功計(jì)算出正確的max_edge,很怪
求次小生成樹
定義:所有生成樹中路徑長(zhǎng)是第二小的樹
可行變換:一棵生成樹換一條邊仍然為生成樹,稱為進(jìn)行了可行變換
臨集:換了邊的生成樹 ∈\in∈ 原來生成樹的臨集
注意
[參考]
1.https://www.bilibili.com/video/BV1CC4y1a7kD?from=search&seid=17175123924411804815&spm_id_from=333.337.0.010.
2.https://blog.csdn.net/CoolCoolCarrot/article/details/100675150?ops_request_misc=&request_id=&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2alles_rank~default-1-100675150.pc_search_es_clickV2&utm_term=%E5%AF%BB%E6%89%BE%E8%88%AA%E6%B5%B7%E8%B7%AF%E7%BA%BF&spm=1018.2226.3001.4187
總結(jié)
以上是生活随笔為你收集整理的EOJ_1094_寻找航海路线的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小程序滑动删除
- 下一篇: EOJ_1102_任务调度问题