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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

poj 2831(次小生成树)

發布時間:2025/3/16 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poj 2831(次小生成树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:給你一幅圖,再給你Q個詢問,每個詢問為id cost,即如果將id這條邊的邊權改為cost的話,這條邊是否可能是最小生成樹中的一條邊

解題思路:將第i條邊(u,v)的權值修改的話,要判斷是否是最小生成樹中的一條邊,首先要把它加入進去,此時必定會引起原來的生成樹成環,所以必定要擦去一條邊,擦去的是哪一條邊,這就利用到了次小生成樹的原理了。

之前寫過一個次小生成樹的題,現在回過頭看,感覺又有點不對了。

這里再總結一次:

首先肯定是構造一顆最小生成樹,接下來就是枚舉不在生成樹里的邊,假定為(u,v),此時應該把它加入到生成樹中,但這樣肯定會形成u->v的環路,此時肯定要刪除u->v這條環路里的邊,刪哪一條呢?肯定是除了邊(u,v)外的最大邊。

現在是如何找到這條最大邊,可以采用dp的思想,即dp[i][j]表示在樹上i->j的最大值(注意,由于是樹,肯定i->j的路徑是唯一的)。我們在做Prim算法時,每次都是加入一個頂點S,我們還應該記錄下頂點S加入到生成樹里,它與誰相連,即我們在更新low[]數組時要記錄的。這樣,我們可以得到狀態方程:dp[i][j] = dp[j][i] = max(dp[j][pre[i]],low[i]),此時i為即將要加入的點,而j是已經在生成樹頂點集合里的點。

完成了一次Prim算法,同樣也可以將dp數組更新好了,那么回到最開始的問題,刪除的邊我們就可以直接用dp[u][v]。


#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int maxn = 100005; const int inf = 0x3f3f3f3f; struct Edge {int u,v,c; }edge[maxn]; int n,m,q; int map[1005][1005],path[1005][1005]; int pre[1005],low[1005]; bool vis[1005],used[1005][1005];int Prim() {int k = 1,ans = 0;memset(path,0,sizeof(path));memset(vis,false,sizeof(vis));memset(used,false,sizeof(used));vis[k] = true;for(int i = 1; i <= n; i++){low[i] = map[k][i];pre[i] = k;}for(int i = 1; i < n; i++){int MIN = inf;for(int j = 1; j <= n; j++)if(vis[j] == false && low[j] < MIN){MIN = low[j];k = j;}ans += MIN;vis[k] = true;used[k][pre[k]] = used[pre[k]][k] = true;for(int j = 1; j <= n; j++){if(vis[j] == true && j != k)path[j][k] = path[k][j] = max(path[j][pre[k]],low[k]);if(vis[j] == false && low[j] > map[k][j]){low[j] = map[k][j];pre[j] = k;}}}return ans; }int main() {while(scanf("%d%d%d",&n,&m,&q)!=EOF){memset(map,inf,sizeof(map));for(int i = 1; i <= m; i++){scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c);map[edge[i].u][edge[i].v] = map[edge[i].v][edge[i].u] = min(map[edge[i].u][edge[i].v],edge[i].c);}int ans = Prim();while(q--){int id,cost;scanf("%d%d",&id,&cost);if(path[edge[id].u][edge[id].v] >= cost)printf("Yes\n");else printf("No\n");}}return 0; }

總結

以上是生活随笔為你收集整理的poj 2831(次小生成树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。