日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

EOJ_1094_寻找航海路线

發(fā)布時(shí)間:2024/4/11 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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; }

求次小生成樹

定義:所有生成樹中路徑長(zhǎng)是第二小的樹
可行變換:一棵生成樹換一條邊仍然為生成樹,稱為進(jìn)行了可行變換
臨集:換了邊的生成樹 ∈\in 原來生成樹的臨集

  • 用定義,得到所有的生成樹(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,很怪
  • [參考]
    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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。